summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBUILD/compile-pentium-debug-max2
-rw-r--r--BitKeeper/etc/config1
-rw-r--r--BitKeeper/etc/logging_ok6
-rwxr-xr-xBuild-tools/Do-pkg13
-rw-r--r--VC++Files/client/mysqlclient.dsp34
-rw-r--r--VC++Files/innobase/innobase.dsp4
-rwxr-xr-xVC++Files/libmysql/libmysql.def94
-rw-r--r--VC++Files/libmysql/libmysql.dsp4
-rw-r--r--VC++Files/mysql.dsw3
-rw-r--r--acinclude.m41
-rw-r--r--client/mysql.cc114
-rw-r--r--client/mysqladmin.c36
-rw-r--r--client/mysqlbinlog.cc58
-rw-r--r--client/mysqldump.c98
-rw-r--r--client/mysqltest.c232
-rw-r--r--configure.in30
-rw-r--r--extra/replace.c41
-rw-r--r--heap/hp_delete.c24
-rw-r--r--heap/hp_extra.c33
-rw-r--r--include/config-win.h1
-rw-r--r--include/errmsg.h45
-rw-r--r--include/m_ctype.h57
-rw-r--r--include/my_base.h20
-rw-r--r--include/my_global.h10
-rw-r--r--include/my_sys.h8
-rw-r--r--include/my_tree.h4
-rw-r--r--include/mysql.h120
-rw-r--r--include/mysql_version.h.in5
-rw-r--r--include/mysqld_error.h4
-rw-r--r--include/sql_common.h2
-rw-r--r--innobase/Makefile.am2
-rw-r--r--innobase/btr/btr0btr.c78
-rw-r--r--innobase/btr/btr0cur.c54
-rw-r--r--innobase/btr/btr0pcur.c4
-rw-r--r--innobase/btr/btr0sea.c66
-rw-r--r--innobase/buf/buf0buf.c10
-rw-r--r--innobase/buf/buf0flu.c13
-rw-r--r--innobase/buf/buf0lru.c24
-rw-r--r--innobase/com/Makefile.am24
-rw-r--r--innobase/com/com0com.c345
-rw-r--r--innobase/com/com0shm.c1130
-rw-r--r--innobase/com/makefilewin12
-rw-r--r--innobase/configure.in3
-rw-r--r--innobase/cry/makefilewin12
-rw-r--r--innobase/data/data0data.c8
-rw-r--r--innobase/dict/dict0boot.c25
-rw-r--r--innobase/dict/dict0crea.c34
-rw-r--r--innobase/dict/dict0dict.c106
-rw-r--r--innobase/dict/dict0load.c22
-rw-r--r--innobase/dict/dict0mem.c6
-rw-r--r--innobase/fil/fil0fil.c12
-rw-r--r--innobase/fsp/fsp0fsp.c111
-rw-r--r--innobase/ha/ha0ha.c9
-rw-r--r--innobase/ha/hash0hash.c38
-rw-r--r--innobase/ibuf/ibuf0ibuf.c30
-rw-r--r--innobase/include/Makefile.am7
-rw-r--r--innobase/include/btr0btr.ic3
-rw-r--r--innobase/include/btr0cur.h10
-rw-r--r--innobase/include/btr0sea.h2
-rw-r--r--innobase/include/btr0sea.ic6
-rw-r--r--innobase/include/buf0buf.h5
-rw-r--r--innobase/include/buf0buf.ic18
-rw-r--r--innobase/include/buf0flu.ic4
-rw-r--r--innobase/include/com0com.h125
-rw-r--r--innobase/include/com0com.ic7
-rw-r--r--innobase/include/com0shm.h103
-rw-r--r--innobase/include/com0shm.ic7
-rw-r--r--innobase/include/data0data.h6
-rw-r--r--innobase/include/data0type.ic2
-rw-r--r--innobase/include/dict0dict.h11
-rw-r--r--innobase/include/dict0dict.ic10
-rw-r--r--innobase/include/dict0mem.h17
-rw-r--r--innobase/include/fut0fut.ic2
-rw-r--r--innobase/include/ha0ha.ic8
-rw-r--r--innobase/include/hash0hash.h75
-rw-r--r--innobase/include/hash0hash.ic8
-rw-r--r--innobase/include/ib_odbc.h149
-rw-r--r--innobase/include/lock0lock.ic2
-rw-r--r--innobase/include/log0log.h4
-rw-r--r--innobase/include/log0log.ic10
-rw-r--r--innobase/include/mach0data.h19
-rw-r--r--innobase/include/mach0data.ic38
-rw-r--r--innobase/include/mem0dbg.ic2
-rw-r--r--innobase/include/mtr0log.h1
-rw-r--r--innobase/include/mtr0mtr.h15
-rw-r--r--innobase/include/odbc0odbc.h20
-rw-r--r--innobase/include/os0file.h61
-rw-r--r--innobase/include/page0cur.h5
-rw-r--r--innobase/include/pars0pars.h31
-rw-r--r--innobase/include/que0que.h25
-rw-r--r--innobase/include/que0que.ic18
-rw-r--r--innobase/include/row0ins.h5
-rw-r--r--innobase/include/row0mysql.h21
-rw-r--r--innobase/include/row0upd.h5
-rw-r--r--innobase/include/row0upd.ic2
-rw-r--r--innobase/include/srv0srv.h4
-rw-r--r--innobase/include/sync0rw.h14
-rw-r--r--innobase/include/sync0rw.ic9
-rw-r--r--innobase/include/sync0sync.h14
-rw-r--r--innobase/include/sync0sync.ic9
-rw-r--r--innobase/include/trx0rseg.ic8
-rw-r--r--innobase/include/trx0sys.ic22
-rw-r--r--innobase/include/trx0trx.h19
-rw-r--r--innobase/include/trx0undo.h14
-rw-r--r--innobase/include/trx0undo.ic4
-rw-r--r--innobase/include/usr0sess.h218
-rw-r--r--innobase/include/usr0sess.ic24
-rw-r--r--innobase/include/usr0types.h2
-rw-r--r--innobase/include/ut0dbg.h23
-rw-r--r--innobase/include/ut0mem.h9
-rw-r--r--innobase/lock/lock0lock.c96
-rw-r--r--innobase/log/log0log.c115
-rw-r--r--innobase/log/log0recv.c50
-rw-r--r--innobase/mem/mem0dbg.c44
-rw-r--r--innobase/mem/mem0pool.c14
-rw-r--r--innobase/mtr/mtr0log.c13
-rw-r--r--innobase/mtr/mtr0mtr.c2
-rw-r--r--innobase/os/os0file.c215
-rw-r--r--innobase/page/page0cur.c9
-rw-r--r--innobase/page/page0page.c4
-rw-r--r--innobase/pars/lexyy.c2
-rw-r--r--innobase/pars/pars0pars.c258
-rw-r--r--innobase/que/que0que.c191
-rw-r--r--innobase/read/read0read.c12
-rw-r--r--innobase/rem/rem0cmp.c2
-rw-r--r--innobase/rem/rem0rec.c4
-rw-r--r--innobase/row/row0ins.c16
-rw-r--r--innobase/row/row0mysql.c40
-rw-r--r--innobase/row/row0purge.c6
-rw-r--r--innobase/row/row0row.c4
-rw-r--r--innobase/row/row0sel.c8
-rw-r--r--innobase/row/row0undo.c2
-rw-r--r--innobase/row/row0upd.c23
-rw-r--r--innobase/row/row0vers.c8
-rw-r--r--innobase/srv/srv0que.c2
-rw-r--r--innobase/srv/srv0srv.c54
-rw-r--r--innobase/srv/srv0start.c3
-rw-r--r--innobase/sync/sync0arr.c36
-rw-r--r--innobase/sync/sync0rw.c34
-rw-r--r--innobase/sync/sync0sync.c75
-rw-r--r--innobase/thr/thr0loc.c12
-rw-r--r--innobase/trx/trx0purge.c37
-rw-r--r--innobase/trx/trx0rec.c6
-rw-r--r--innobase/trx/trx0roll.c32
-rw-r--r--innobase/trx/trx0rseg.c11
-rw-r--r--innobase/trx/trx0sys.c23
-rw-r--r--innobase/trx/trx0trx.c94
-rw-r--r--innobase/trx/trx0undo.c107
-rw-r--r--innobase/usr/usr0sess.c519
-rw-r--r--innobase/ut/ut0dbg.c8
-rw-r--r--innobase/ut/ut0mem.c24
-rw-r--r--isam/isamchk.c2
-rw-r--r--libmysql/client_settings.h3
-rw-r--r--libmysql/errmsg.c19
-rw-r--r--libmysql/libmysql.c761
-rw-r--r--libmysql/libmysql.def18
-rw-r--r--libmysqld/lib_sql.cc25
-rw-r--r--myisam/ft_boolean_search.c8
-rw-r--r--myisam/mi_check.c6
-rw-r--r--myisam/mi_extra.c31
-rw-r--r--myisam/myisam_ftdump.c2
-rw-r--r--myisam/myisamchk.c4
-rw-r--r--mysql-test/include/system_db_struct.inc12
-rw-r--r--mysql-test/install_test_db.sh33
-rw-r--r--mysql-test/mysql-test-run.sh72
-rw-r--r--mysql-test/r/alter_table.result16
-rw-r--r--mysql-test/r/create.result75
-rw-r--r--mysql-test/r/ctype_utf8.result25
-rw-r--r--mysql-test/r/date_formats.result113
-rw-r--r--mysql-test/r/derived.result10
-rw-r--r--mysql-test/r/drop.result1
-rw-r--r--mysql-test/r/fulltext.result4
-rw-r--r--mysql-test/r/fulltext_var.result2
-rw-r--r--mysql-test/r/func_if.result6
-rw-r--r--mysql-test/r/func_like.result6
-rw-r--r--mysql-test/r/func_misc.result3
-rw-r--r--mysql-test/r/func_sapdb.result25
-rw-r--r--mysql-test/r/func_str.result24
-rw-r--r--mysql-test/r/func_time.result27
-rw-r--r--mysql-test/r/gis.result212
-rw-r--r--mysql-test/r/grant.result31
-rw-r--r--mysql-test/r/insert.result239
-rw-r--r--mysql-test/r/insert_update.result38
-rw-r--r--mysql-test/r/lowercase0.require3
-rw-r--r--mysql-test/r/lowercase_table.result18
-rw-r--r--mysql-test/r/lowercase_table2.result15
-rw-r--r--mysql-test/r/lowercase_table3.result10
-rw-r--r--mysql-test/r/lowercase_table_qcache.result24
-rw-r--r--mysql-test/r/multi_update.result39
-rw-r--r--mysql-test/r/mysqlbinlog.result11
-rw-r--r--mysql-test/r/mysqldump.result86
-rw-r--r--mysql-test/r/order_by.result32
-rw-r--r--mysql-test/r/query_cache.result17
-rw-r--r--mysql-test/r/rpl000009.result12
-rw-r--r--mysql-test/r/rpl_error_ignored_table.result27
-rw-r--r--mysql-test/r/rpl_optimize.result27
-rw-r--r--mysql-test/r/rpl_trunc_binlog.result2
-rw-r--r--mysql-test/r/show_check.result101
-rw-r--r--mysql-test/r/subselect.result95
-rw-r--r--mysql-test/r/subselect2.result4
-rw-r--r--mysql-test/r/system_mysql_db.result123
-rw-r--r--mysql-test/r/system_mysql_db_refs.result67
-rw-r--r--mysql-test/r/true.require2
-rw-r--r--mysql-test/r/type_time.result2
-rw-r--r--mysql-test/r/union.result15
-rw-r--r--mysql-test/r/variables.result29
-rw-r--r--mysql-test/t/alter_table.test11
-rw-r--r--mysql-test/t/create.test51
-rw-r--r--mysql-test/t/ctype_utf8.test23
-rw-r--r--mysql-test/t/date_formats.test31
-rw-r--r--mysql-test/t/derived.test12
-rw-r--r--mysql-test/t/drop.test2
-rw-r--r--mysql-test/t/fulltext.test3
-rw-r--r--mysql-test/t/func_if.test6
-rw-r--r--mysql-test/t/func_like.test8
-rw-r--r--mysql-test/t/func_math.test10
-rw-r--r--mysql-test/t/func_misc.test2
-rw-r--r--mysql-test/t/func_sapdb.test6
-rw-r--r--mysql-test/t/func_str.test25
-rw-r--r--mysql-test/t/func_time.test10
-rw-r--r--mysql-test/t/gis.test201
-rw-r--r--mysql-test/t/grant.test17
-rw-r--r--mysql-test/t/insert.test53
-rw-r--r--mysql-test/t/insert_update.test22
-rw-r--r--mysql-test/t/lowercase_table.test26
-rw-r--r--mysql-test/t/lowercase_table2.test11
-rw-r--r--mysql-test/t/lowercase_table3-master.opt (renamed from mysql-test/t/lowercase_table2-master.opt)0
-rw-r--r--mysql-test/t/lowercase_table3.test37
-rw-r--r--mysql-test/t/lowercase_table_qcache-master.opt1
-rw-r--r--mysql-test/t/lowercase_table_qcache.test29
-rw-r--r--mysql-test/t/multi_update.test35
-rw-r--r--mysql-test/t/mysqlbinlog.test1
-rw-r--r--mysql-test/t/mysqldump.test13
-rw-r--r--mysql-test/t/order_by.test25
-rw-r--r--mysql-test/t/query_cache.test17
-rw-r--r--mysql-test/t/rpl000009.test15
-rw-r--r--mysql-test/t/rpl_error_ignored_table-slave.opt2
-rw-r--r--mysql-test/t/rpl_error_ignored_table.test30
-rw-r--r--mysql-test/t/rpl_optimize.test43
-rw-r--r--mysql-test/t/show_check.test70
-rw-r--r--mysql-test/t/subselect.test45
-rw-r--r--mysql-test/t/system_mysql_db.test8
-rw-r--r--mysql-test/t/system_mysql_db_fix-master.opt1
-rw-r--r--mysql-test/t/system_mysql_db_fix.test78
-rw-r--r--mysql-test/t/system_mysql_db_refs.test101
-rw-r--r--mysql-test/t/union.test13
-rw-r--r--mysql-test/t/variables.test26
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/charset.c2
-rw-r--r--mysys/charset2html.c16
-rw-r--r--mysys/hash.c8
-rw-r--r--mysys/mf_iocache.c6
-rw-r--r--mysys/mf_pack.c30
-rw-r--r--mysys/mf_soundex.c4
-rw-r--r--mysys/my_getopt.c15
-rw-r--r--mysys/my_getsystime.c48
-rw-r--r--mysys/test_fn.c3
-rw-r--r--mysys/tree.c21
-rw-r--r--pstack/bucomm.h6
-rw-r--r--pstack/budbg.h6
-rw-r--r--pstack/pstack.c3
-rw-r--r--regex/regcomp.c24
-rw-r--r--scripts/mysql_create_system_tables.sh2
-rw-r--r--scripts/mysql_fix_privilege_tables.sh55
-rw-r--r--scripts/mysql_fix_privilege_tables.sql65
-rw-r--r--scripts/mysql_install_db.sh2
-rw-r--r--scripts/mysqlhotcopy.sh5
-rw-r--r--sql-common/client.c207
-rw-r--r--sql/field.cc216
-rw-r--r--sql/field.h4
-rw-r--r--sql/field_conv.cc12
-rw-r--r--sql/gen_lex_hash.cc1
-rw-r--r--sql/gstream.cc177
-rw-r--r--sql/gstream.h41
-rw-r--r--sql/ha_berkeley.cc4
-rw-r--r--sql/ha_berkeley.h2
-rw-r--r--sql/ha_innodb.cc82
-rw-r--r--sql/ha_innodb.h1
-rw-r--r--sql/ha_isam.cc1
-rw-r--r--sql/ha_isam.h1
-rw-r--r--sql/ha_myisam.cc1
-rw-r--r--sql/ha_myisam.h2
-rw-r--r--sql/handler.cc76
-rw-r--r--sql/item.cc192
-rw-r--r--sql/item.h173
-rw-r--r--sql/item_cmpfunc.cc195
-rw-r--r--sql/item_cmpfunc.h35
-rw-r--r--sql/item_create.cc6
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_func.cc167
-rw-r--r--sql/item_func.h35
-rw-r--r--sql/item_geofunc.cc481
-rw-r--r--sql/item_geofunc.h2
-rw-r--r--sql/item_row.cc20
-rw-r--r--sql/item_strfunc.cc129
-rw-r--r--sql/item_strfunc.h38
-rw-r--r--sql/item_subselect.cc33
-rw-r--r--sql/item_subselect.h1
-rw-r--r--sql/item_sum.cc38
-rw-r--r--sql/item_sum.h31
-rw-r--r--sql/item_timefunc.cc331
-rw-r--r--sql/item_timefunc.h103
-rw-r--r--sql/item_uniq.h5
-rw-r--r--sql/lex.h1
-rw-r--r--sql/lex_symbol.h9
-rw-r--r--sql/lock.cc7
-rw-r--r--sql/log_event.cc186
-rw-r--r--sql/mf_iocache.cc6
-rw-r--r--sql/mysql_priv.h35
-rw-r--r--sql/mysqld.cc114
-rw-r--r--sql/opt_range.cc16
-rw-r--r--sql/protocol.h5
-rw-r--r--sql/repl_failsafe.cc21
-rw-r--r--sql/set_var.cc143
-rw-r--r--sql/set_var.h33
-rw-r--r--sql/share/czech/errmsg.txt8
-rw-r--r--sql/share/danish/errmsg.txt8
-rw-r--r--sql/share/dutch/errmsg.txt8
-rw-r--r--sql/share/english/errmsg.txt8
-rw-r--r--sql/share/estonian/errmsg.txt8
-rw-r--r--sql/share/french/errmsg.txt8
-rw-r--r--sql/share/german/errmsg.txt6
-rw-r--r--sql/share/greek/errmsg.txt8
-rw-r--r--sql/share/hungarian/errmsg.txt8
-rw-r--r--sql/share/italian/errmsg.txt8
-rw-r--r--sql/share/japanese/errmsg.txt8
-rw-r--r--sql/share/korean/errmsg.txt8
-rw-r--r--sql/share/norwegian-ny/errmsg.txt8
-rw-r--r--sql/share/norwegian/errmsg.txt8
-rw-r--r--sql/share/polish/errmsg.txt8
-rw-r--r--sql/share/portuguese/errmsg.txt8
-rw-r--r--sql/share/romanian/errmsg.txt8
-rw-r--r--sql/share/russian/errmsg.txt8
-rw-r--r--sql/share/serbian/errmsg.txt6
-rw-r--r--sql/share/slovak/errmsg.txt8
-rw-r--r--sql/share/spanish/errmsg.txt8
-rw-r--r--sql/share/swedish/errmsg.txt6
-rw-r--r--sql/share/ukrainian/errmsg.txt8
-rw-r--r--sql/slave.cc60
-rw-r--r--sql/slave.h52
-rw-r--r--sql/spatial.cc1800
-rw-r--r--sql/spatial.h494
-rw-r--r--sql/sql_acl.cc18
-rw-r--r--sql/sql_base.cc70
-rw-r--r--sql/sql_cache.cc48
-rw-r--r--sql/sql_cache.h1
-rw-r--r--sql/sql_class.cc19
-rw-r--r--sql/sql_class.h33
-rw-r--r--sql/sql_db.cc78
-rw-r--r--sql/sql_delete.cc9
-rw-r--r--sql/sql_derived.cc6
-rw-r--r--sql/sql_handler.cc8
-rw-r--r--sql/sql_help.cc21
-rw-r--r--sql/sql_insert.cc41
-rw-r--r--sql/sql_lex.cc6
-rw-r--r--sql/sql_lex.h3
-rw-r--r--sql/sql_list.h5
-rw-r--r--sql/sql_parse.cc145
-rw-r--r--sql/sql_prepare.cc800
-rw-r--r--sql/sql_repl.cc2
-rw-r--r--sql/sql_select.cc145
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_string.cc16
-rw-r--r--sql/sql_string.h16
-rw-r--r--sql/sql_table.cc77
-rw-r--r--sql/sql_udf.cc8
-rw-r--r--sql/sql_union.cc19
-rw-r--r--sql/sql_update.cc21
-rw-r--r--sql/sql_yacc.yy95
-rw-r--r--sql/structs.h14
-rw-r--r--sql/table.cc33
-rw-r--r--sql/time.cc85
-rw-r--r--strings/ctype-big5.c6
-rw-r--r--strings/ctype-bin.c3
-rw-r--r--strings/ctype-czech.c3
-rw-r--r--strings/ctype-euc_kr.c6
-rw-r--r--strings/ctype-extra.c1
-rw-r--r--strings/ctype-gb2312.c6
-rw-r--r--strings/ctype-gbk.c6
-rw-r--r--strings/ctype-latin1.c9
-rw-r--r--strings/ctype-simple.c20
-rw-r--r--strings/ctype-sjis.c6
-rw-r--r--strings/ctype-tis620.c6
-rw-r--r--strings/ctype-ucs2.c89
-rw-r--r--strings/ctype-ujis.c6
-rw-r--r--strings/ctype-utf8.c6
-rw-r--r--strings/ctype-win1250ch.c3
-rw-r--r--strings/strtod.c24
-rw-r--r--strings/uca-dump.c258
-rw-r--r--support-files/Makefile.am1
-rw-r--r--support-files/my-innodb-heavy-4G.cnf.sh8
-rw-r--r--tests/client_test.c82
-rw-r--r--tests/thread_test.c2
394 files changed, 10978 insertions, 8243 deletions
diff --git a/BUILD/compile-pentium-debug-max b/BUILD/compile-pentium-debug-max
index f8cf19b2132..9c3c80c3382 100755
--- a/BUILD/compile-pentium-debug-max
+++ b/BUILD/compile-pentium-debug-max
@@ -8,6 +8,6 @@ c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
-extra_configs="$extra_configs --with-berkeley-db --with-innodb --without-isam --with-embedded-server --with-openssl --with-raid"
+extra_configs="$extra_configs --with-berkeley-db --with-innodb --without-isam --with-embedded-server --with-openssl --with-raid --with-vio"
. "$path/FINISH.sh"
diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config
index ea30f368b52..c609fcdbd49 100644
--- a/BitKeeper/etc/config
+++ b/BitKeeper/etc/config
@@ -71,3 +71,4 @@ hours:
[arjen:]checkout:get
[nick:]checkout:get
checkout:edit
+eoln:unix
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index b0016735d84..db98622657e 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -11,6 +11,7 @@ administrador@light.hegel.local
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
akishkin@work.mysql.com
antony@ltantony.rdg.cyberkinetica.homeunix.net
+arjen@bitbike.com
arjen@co3064164-a.bitbike.com
arjen@fred.bitbike.com
arjen@george.bitbike.com
@@ -36,6 +37,7 @@ guilhem@mysql.com
gweir@build.mysql.com
gweir@work.mysql.com
harrison@mysql.com
+harry@corona.lordblink.com
heikki@donna.mysql.fi
heikki@hundin.mysql.fi
heikki@rescue.
@@ -47,6 +49,7 @@ hf@deer.mysql.r18.ru
hf@genie.(none)
igor@hundin.mysql.fi
igor@rurik.mysql.com
+ingo@mysql.com
jani@dsl-jkl1657.dial.inet.fi
jani@dsl-kpogw4gb5.dial.inet.fi
jani@hynda.(none)
@@ -57,6 +60,7 @@ jani@rhols221.arenanet.fi
jani@ua126d19.elisa.omakaista.fi
jani@ua141d10.elisa.omakaista.fi
jani@ua167d18.elisa.omakaista.fi
+jani@ua72d24.elisa.omakaista.fi
jcole@abel.spaceapes.com
jcole@main.burghcom.com
jcole@mugatu.spaceapes.com
@@ -94,6 +98,7 @@ monty@work.mysql.com
mwagner@cash.mwagner.org
mwagner@evoq.mwagner.org
mwagner@work.mysql.com
+mydev@mysql.com
mysql@home.(none)
mysqldev@build.mysql2.com
nick@mysql.com
@@ -144,6 +149,7 @@ tonu@hundin.mysql.fi
tonu@volk.internalnet
tonu@x153.internalnet
tonu@x3.internalnet
+ulli@morbus.(none)
venu@hundin.mysql.fi
venu@myvenu.com
venu@work.mysql.com
diff --git a/Build-tools/Do-pkg b/Build-tools/Do-pkg
index 4d0f120c6e3..2fd1946ed0e 100755
--- a/Build-tools/Do-pkg
+++ b/Build-tools/Do-pkg
@@ -61,6 +61,12 @@ else
}
$PM= "/Developer/Applications/PackageMaker.app/Contents/MacOS/PackageMaker";
+# Try another location on 10.3.3
+unless (-e "$PM")
+{
+ $PM= "/Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker";
+}
+
$TMP= $ENV{TMPDIR};
$TMP eq "" ? $TMP= $TMP . "/PKGBUILD.$$": $TMP= "/tmp/PKGBUILD.$$";
$PKGROOT= "$TMP/PMROOT";
@@ -79,6 +85,9 @@ $BUILDDIR= "$PWD/$HOST";
$SRCBASEDIR= <$BUILDDIR/mysql*-$VERSION>;
$SUPFILEDIR= <$SRCBASEDIR/support-files/MacOSX>;
$TAR= <$BUILDDIR/$NAME-apple-darwin*-powerpc.tar.gz>;
+$TAR =~ /.*\/$NAME(.*)\.tar\.gz$/;
+$ARCH= $1;
+$NAME= $NAME . $ARCH;
$INFO= <$SUPFILEDIR/Info.plist>;
$DESC= <$SUPFILEDIR/Description.plist>;
$SI_INFO= <$SUPFILEDIR/StartupItem.Info.plist>;
@@ -167,7 +176,7 @@ unless (-f "$RESOURCE_DIR/License.txt");
&logger("Extracting $TAR to $PKGROOT");
&run_command("gnutar zxf $TAR -C $PKGROOT", "Unable to extract $TAR!");
&run_command("cd $PKGROOT ; ln -s mysql* ./mysql", "Unable to create symlink!");
-&run_command("chown -R root.wheel $PKGROOT/*", "Cannot chown $PKGROOT!");
+&run_command("chown -R root:wheel $PKGROOT/*", "Cannot chown $PKGROOT!");
# Now build the PGK using PackageMaker
# The "|| true" is a nasty hack to work around a problem with Package Maker
@@ -196,7 +205,7 @@ unless ($opt_skip_si)
copy("$SI_PARAMS", "$PKGROOT/MySQL/")
or &abort("Error copying $SI_PARAMS!");
chmod(0644, "$PKGROOT/MySQL/" . basename("$SI_PARAMS"));
- &run_command("chown -R root.wheel $PKGROOT/*", "Cannot chown $PKGROOT!");
+ &run_command("chown -R root:wheel $PKGROOT/*", "Cannot chown $PKGROOT!");
copy("$SI_POST", "$RESOURCE_DIR/postinstall")
or &abort("Error copying $SI_POST!");
chmod(0644, "$RESOURCE_DIR/postinstall");
diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp
index 58ec040a63d..46a4d2c89eb 100644
--- a/VC++Files/client/mysqlclient.dsp
+++ b/VC++Files/client/mysqlclient.dsp
@@ -7,25 +7,25 @@
CFG=mysqlclient - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlclient.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "mysqlclient.mak" CFG="mysqlclient - Win32 Debug"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "mysqlclient - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "mysqlclient - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=xicl6.exe
+CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "mysqlclient - Win32 Release"
@@ -48,7 +48,7 @@ RSC=rc.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=xilink6.exe -lib
+LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_release\mysqlclient.lib"
@@ -72,11 +72,11 @@ LIB32=xilink6.exe -lib
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=xilink6.exe -lib
+LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\mysqlclient.lib"
-!ENDIF
+!ENDIF
# Begin Target
@@ -252,7 +252,7 @@ SOURCE=..\mysys\mf_iocache2.c
# ADD CPP /Od
-!ENDIF
+!ENDIF
# End Source File
# Begin Source File
@@ -310,6 +310,10 @@ SOURCE=..\mysys\my_error.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\my_file.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\my_fopen.c
# End Source File
# Begin Source File
@@ -358,10 +362,6 @@ SOURCE=..\mysys\my_open.c
# End Source File
# Begin Source File
-SOURCE=..\mysys\my_file.c
-# End Source File
-# Begin Source File
-
SOURCE=..\mysys\my_pread.c
# End Source File
# Begin Source File
@@ -490,6 +490,10 @@ SOURCE=..\strings\strnmov.c
# End Source File
# Begin Source File
+SOURCE=..\strings\strtod.c
+# End Source File
+# Begin Source File
+
SOURCE=..\strings\strtoll.c
# End Source File
# Begin Source File
diff --git a/VC++Files/innobase/innobase.dsp b/VC++Files/innobase/innobase.dsp
index 42d7001bdd4..e32f242be80 100644
--- a/VC++Files/innobase/innobase.dsp
+++ b/VC++Files/innobase/innobase.dsp
@@ -280,10 +280,6 @@ SOURCE=.\mtr\mtr0mtr.c
# End Source File
# Begin Source File
-SOURCE=.\odbc\odbc0odbc.c
-# End Source File
-# Begin Source File
-
SOURCE=.\os\os0file.c
# End Source File
# Begin Source File
diff --git a/VC++Files/libmysql/libmysql.def b/VC++Files/libmysql/libmysql.def
deleted file mode 100755
index 726a53864f3..00000000000
--- a/VC++Files/libmysql/libmysql.def
+++ /dev/null
@@ -1,94 +0,0 @@
-LIBRARY LIBMYSQL
-DESCRIPTION 'MySQL 3.23 Client Library'
-VERSION 2.5
-EXPORTS
- mysql_affected_rows
- mysql_close
- mysql_connect
- mysql_create_db
- mysql_data_seek
- mysql_debug
- mysql_drop_db
- mysql_dump_debug_info
- mysql_eof
- mysql_errno
- mysql_error
- mysql_escape_string
- mysql_fetch_field
- mysql_fetch_field_direct
- mysql_fetch_fields
- mysql_fetch_lengths
- mysql_fetch_row
- mysql_field_count
- mysql_field_seek
- mysql_field_tell
- mysql_free_result
- mysql_get_client_info
- mysql_get_host_info
- mysql_get_proto_info
- mysql_get_server_info
- mysql_info
- mysql_init
- mysql_insert_id
- mysql_kill
- mysql_list_dbs
- mysql_list_fields
- mysql_list_processes
- mysql_list_tables
- mysql_num_fields
- mysql_num_rows
- mysql_odbc_escape_string
- mysql_options
- mysql_ping
- mysql_query
- mysql_real_connect
- mysql_real_query
- mysql_refresh
- mysql_row_seek
- mysql_row_tell
- mysql_select_db
- mysql_shutdown
- mysql_stat
- mysql_store_result
- mysql_thread_id
- mysql_use_result
- bmove_upp
- delete_dynamic
- _dig_vec
- init_dynamic_array
- insert_dynamic
- int2str
- is_prefix
- list_add
- list_delete
- max_allowed_packet
- my_casecmp
- my_init
- my_end
- my_strdup
- my_malloc
- my_memdup
- my_no_flags_free
- my_realloc
- my_thread_end
- my_thread_init
- net_buffer_length
- set_dynamic
- strcend
- strdup_root
- strfill
- strinstr
- strmake
- strmov
- strxmov
- myodbc_remove_escape
- mysql_thread_safe
- mysql_character_set_name
- mysql_change_user
- mysql_send_query
- mysql_read_query_result
- mysql_real_escape_string
- load_defaults
- free_defaults
-
-
diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp
index ca7ff2823ec..8b36016f8c1 100644
--- a/VC++Files/libmysql/libmysql.dsp
+++ b/VC++Files/libmysql/libmysql.dsp
@@ -499,6 +499,10 @@ SOURCE=..\strings\strxmov.c
# End Source File
# Begin Source File
+SOURCE=..\strings\strxnmov.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\thr_mutex.c
# End Source File
# Begin Source File
diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw
index 4db81e31755..e0df167f58d 100644
--- a/VC++Files/mysql.dsw
+++ b/VC++Files/mysql.dsw
@@ -38,6 +38,9 @@ Package=<5>
Package=<4>
{{{
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
}}}
###############################################################################
diff --git a/acinclude.m4 b/acinclude.m4
index 1fc357ff7c6..2eb45b2e8ce 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1275,7 +1275,6 @@ dnl circular references.
\$(top_builddir)/innobase/page/libpage.a\
\$(top_builddir)/innobase/rem/librem.a\
\$(top_builddir)/innobase/thr/libthr.a\
- \$(top_builddir)/innobase/com/libcom.a\
\$(top_builddir)/innobase/sync/libsync.a\
\$(top_builddir)/innobase/data/libdata.a\
\$(top_builddir)/innobase/mach/libmach.a\
diff --git a/client/mysql.cc b/client/mysql.cc
index eb466a86c91..31f563d4116 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -25,7 +25,7 @@
* Matt Wagner <matt@mysql.com>
* Jeremy Cole <jcole@mysql.com>
* Tonu Samuel <tonu@mysql.com>
- * Harrison Fisk <hcfisk@buffalo.edu>
+ * Harrison Fisk <harrison@mysql.com>
*
**/
@@ -289,10 +289,25 @@ static const char *server_default_groups[]=
{ "server", "embedded", "mysql_SERVER", 0 };
#ifdef HAVE_READLINE
+/*
+ HIST_ENTRY is defined for libedit, but not for the real readline
+ Need to redefine it for real readline to find it
+*/
+#if !defined(USE_LIBEDIT_INTERFACE)
+typedef struct _hist_entry {
+ const char *line;
+ const char *data;
+} HIST_ENTRY;
+#endif
+
extern "C" int add_history(const char *command); /* From readline directory */
extern "C" int read_history(const char *command);
extern "C" int write_history(const char *command);
+extern "C" HIST_ENTRY *history_get(int num);
+extern "C" int history_length;
+static int not_in_history(const char *line);
static void initialize_readline (char *name);
+static void fix_history(String *final_command);
#endif
static COMMANDS *find_command (char *name,char cmd_name);
@@ -604,10 +619,10 @@ static struct my_option my_long_options[] =
(gptr*) &current_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"safe-updates", 'U', "Only allow UPDATE and DELETE that uses keys.",
- (gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, OPT_ARG, 0, 0,
+ (gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
{"i-am-a-dummy", 'U', "Synonym for option --safe-updates, -U.",
- (gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, OPT_ARG, 0, 0,
+ (gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
{"verbose", 'v', "Write more. (-v -v -v gives the table output format).", 0,
0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -937,7 +952,7 @@ static int read_lines(bool execute_commands)
if (glob_buffer.is_empty()) // If buffer was emptied
in_string=0;
#ifdef HAVE_READLINE
- if (status.add_to_history)
+ if (status.add_to_history && not_in_history(line))
add_history(line);
#endif
continue;
@@ -1014,7 +1029,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
if (!line[0] && buffer.is_empty())
return 0;
#ifdef HAVE_READLINE
- if (status.add_to_history && line[0])
+ if (status.add_to_history && line[0] && not_in_history(line))
add_history(line);
#endif
#ifdef USE_MB
@@ -1169,6 +1184,75 @@ int no_completion()
return 0; /* No filename completion */
}
+/* glues pieces of history back together if in pieces */
+static void fix_history(String *final_command)
+{
+ int total_lines = 1;
+ char *ptr = final_command->c_ptr();
+ String fixed_buffer; /* Converted buffer */
+ char str_char = '\0'; /* Character if we are in a string or not */
+
+ /* find out how many lines we have and remove newlines */
+ while (*ptr != '\0')
+ {
+ switch (*ptr) {
+ /* string character */
+ case '"':
+ case '\'':
+ case '`':
+ if (str_char == '\0') /* open string */
+ str_char = *ptr;
+ else if (str_char == *ptr) /* close string */
+ str_char = '\0';
+ fixed_buffer.append(ptr,1);
+ break;
+ case '\n':
+ /*
+ not in string, change to space
+ if in string, leave it alone
+ */
+ fixed_buffer.append(str_char == '\0' ? " " : "\n");
+ total_lines++;
+ break;
+ case '\\':
+ fixed_buffer.append('\\');
+ /* need to see if the backslash is escaping anything */
+ if (str_char)
+ {
+ ptr++;
+ /* special characters that need escaping */
+ if (*ptr == '\'' || *ptr == '"' || *ptr == '\\')
+ fixed_buffer.append(ptr,1);
+ else
+ ptr--;
+ }
+ break;
+
+ default:
+ fixed_buffer.append(ptr,1);
+ }
+ ptr++;
+ }
+ if (total_lines > 1)
+ add_history(fixed_buffer.ptr());
+}
+
+/*
+ returns 0 if line matches the previous history entry
+ returns 1 if the line doesn't match the previous history entry
+*/
+static int not_in_history(const char *line)
+{
+ HIST_ENTRY *oldhist = history_get(history_length);
+ int num;
+
+ if (oldhist == 0)
+ return 1;
+ if (strcmp(oldhist->line,line) == 0)
+ return 0;
+ return 1;
+}
+
static void initialize_readline (char *name)
{
/* Allow conditional parsing of the ~/.inputrc file. */
@@ -1631,6 +1715,10 @@ com_help(String *buffer __attribute__((unused)),
static int
com_clear(String *buffer,char *line __attribute__((unused)))
{
+#ifdef HAVE_READLINE
+ if (status.add_to_history)
+ fix_history(buffer);
+#endif
buffer->length(0);
return 0;
}
@@ -1690,6 +1778,16 @@ com_go(String *buffer,char *line __attribute__((unused)))
timer=start_timer();
error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length());
+
+#ifdef HAVE_READLINE
+ if (status.add_to_history)
+ {
+ buffer->append(vertical ? "\\G" : delimiter);
+ /* Append final command onto history */
+ fix_history(buffer);
+ }
+#endif
+
if (error)
{
buffer->length(0); // Remove query on error
@@ -3085,6 +3183,8 @@ static const char* construct_prompt()
processed_prompt.append(' ');
break;
case 'R':
+ if (t->tm_hour < 10)
+ processed_prompt.append('0');
add_int_to_prompt(t->tm_hour);
break;
case 'r':
@@ -3092,6 +3192,8 @@ static const char* construct_prompt()
getHour = t->tm_hour % 12;
if (getHour == 0)
getHour=12;
+ if (getHour < 10)
+ processed_prompt.append('0');
add_int_to_prompt(getHour);
break;
case 'm':
@@ -3117,6 +3219,8 @@ static const char* construct_prompt()
processed_prompt.append(strtok(dateTime,"\n"));
break;
case 's':
+ if (t->tm_sec < 10)
+ processed_prompt.append('0');
add_int_to_prompt(t->tm_sec);
break;
case 'w':
diff --git a/client/mysqladmin.c b/client/mysqladmin.c
index f263d321a7b..a2cce3782d6 100644
--- a/client/mysqladmin.c
+++ b/client/mysqladmin.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2000-2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -140,7 +140,7 @@ static struct my_option my_long_options[] =
NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"port", 'P', "Port number to use for connection.", (gptr*) &tcp_port,
- (gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0},
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"relative", 'r',
@@ -440,6 +440,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
}
}
+
/*
Execute a command.
Return 0 on ok
@@ -450,6 +451,14 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
const char *status;
+ /*
+ MySQL documentation relies on the fact that mysqladmin will
+ execute commands in the order specified, e.g.
+ mysqladmin -u root flush-privileges password "newpassword"
+ to reset a lost root password.
+ If this behaviour is ever changed, Docs should be notified.
+ */
+
struct rand_struct rand_st;
for (; argc > 0 ; argv++,argc--)
@@ -787,9 +796,26 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
if (mysql_query(mysql,buff))
{
- my_printf_error(0,"unable to change password; error: '%s'",
- MYF(ME_BELL),mysql_error(mysql));
- return -1;
+ if (mysql_errno(mysql)!=1290)
+ {
+ my_printf_error(0,"unable to change password; error: '%s'",
+ MYF(ME_BELL),mysql_error(mysql));
+ return -1;
+ }
+ else
+ {
+ /*
+ We don't try to execute 'update mysql.user set..'
+ because we can't perfectly find out the host
+ */
+ my_printf_error(0,"\n"
+ "You cannot use 'password' command as mysqld runs\n"
+ " with grant tables disabled (was started with"
+ " --skip-grant-tables).\n"
+ "Use: \"mysqladmin flush-privileges password '*'\""
+ " instead", MYF(ME_BELL));
+ return -1;
+ }
}
argc--; argv++;
break;
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 50c6e8ca6dc..0f3260e903d 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -443,9 +443,9 @@ static struct my_option my_long_options[] =
{"user", 'u', "Connect to the remote server as username.",
(gptr*) &user, (gptr*) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0,
0, 0},
- {"local-load", 'l', "Prepare files for local load in directory.",
+ {"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.",
(gptr*) &dirname_for_local_load, (gptr*) &dirname_for_local_load, 0,
- GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
@@ -579,6 +579,7 @@ static int parse_args(int *argc, char*** argv)
static MYSQL* safe_connect()
{
MYSQL *local_mysql = mysql_init(NULL);
+
if (!local_mysql)
die("Failed on mysql_init");
@@ -651,7 +652,7 @@ static int dump_remote_log_entries(const char* logname)
{
char buf[128];
char last_db[FN_REFLEN+1] = "";
- uint len;
+ uint len, logname_len;
NET* net = &mysql->net;
int old_format;
DBUG_ENTER("dump_remote_log_entries");
@@ -668,16 +669,16 @@ static int dump_remote_log_entries(const char* logname)
}
int4store(buf, position);
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
- len = (uint) strlen(logname);
+ logname_len = (uint) strlen(logname);
int4store(buf + 6, 0);
- memcpy(buf + 10, logname,len);
- if (simple_command(mysql, COM_BINLOG_DUMP, buf, len + 10, 1))
+ memcpy(buf + 10, logname, logname_len);
+ if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
{
fprintf(stderr,"Got fatal error sending the log dump command\n");
DBUG_RETURN(1);
}
- my_off_t old_off= 0;
+ my_off_t old_off= position;
ulonglong rec_count= 0;
char fname[FN_REFLEN+1];
@@ -706,6 +707,37 @@ static int dump_remote_log_entries(const char* logname)
Log_event_type type= ev->get_type_code();
if (!old_format || ( type != LOAD_EVENT && type != CREATE_FILE_EVENT))
{
+ /*
+ If this is a Rotate event, maybe it's the end of the requested binlog;
+ in this case we are done (stop transfer).
+ This is suitable for binlogs, not relay logs (but for now we don't read
+ relay logs remotely because the server is not able to do that). If one
+ day we read relay logs remotely, then we will have a problem with the
+ detection below: relay logs contain Rotate events which are about the
+ binlogs, so which would trigger the end-detection below.
+ */
+ if (ev->get_type_code() == ROTATE_EVENT)
+ {
+ Rotate_log_event *rev= (Rotate_log_event *)ev;
+ /*
+ If this is a fake Rotate event, and not about our log, we can stop
+ transfer. If this a real Rotate event (so it's not about our log,
+ it's in our log describing the next log), we print it (because it's
+ part of our log) and then we will stop when we receive the fake one
+ soon.
+ */
+ if (rev->when == 0)
+ {
+ if ((rev->ident_len != logname_len) ||
+ memcmp(rev->new_log_ident, logname, logname_len))
+ DBUG_RETURN(0);
+ /*
+ Otherwise, this is a fake Rotate for our log, at the very beginning
+ for sure. Skip it.
+ */
+ continue;
+ }
+ }
if (process_event(&rec_count,last_db,ev,old_off,old_format))
DBUG_RETURN(1);
}
@@ -734,12 +766,10 @@ static int dump_remote_log_entries(const char* logname)
/*
Let's adjust offset for remote log as for local log to produce
- similar text..
+ similar text. As we don't print the fake Rotate event, all events are
+ real so we can simply add the length.
*/
- if (old_off)
- old_off+= len-1;
- else
- old_off= BIN_LOG_HEADER_SIZE;
+ old_off+= len-1;
}
DBUG_RETURN(0);
}
@@ -893,7 +923,7 @@ int main(int argc, char** argv)
{
if (init_tmpdir(&tmpdir, 0))
exit(1);
- dirname_for_local_load= my_tmpdir(&tmpdir);
+ dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME);
}
if (load_processor.init())
@@ -904,6 +934,8 @@ int main(int argc, char** argv)
load_processor.init_by_cur_dir();
exit_value= 0;
+ fprintf(result_file,
+ "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
while (--argc >= 0)
{
if (dump_log_entries(*(argv++)))
diff --git a/client/mysqldump.c b/client/mysqldump.c
index e9ca0d975a9..8a5e70649a1 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -43,6 +43,7 @@
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
+#include <assert.h>
#include "client_priv.h"
#include "mysql.h"
@@ -63,7 +64,6 @@
#define SHOW_NULL 2
#define SHOW_DEFAULT 4
#define SHOW_EXTRA 5
-#define QUOTE_CHAR '`'
/* Size of buffer for dump's select query */
#define QUERY_LENGTH 1536
@@ -79,16 +79,18 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1,
ignore=0,opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_names=0,
- opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0,
- opt_delete_master_logs=0, tty_password=0,
+ opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0,
+ opt_delete_master_logs=0, tty_password=0,
opt_single_transaction=0, opt_comments= 0, opt_compact= 0;
-static MYSQL mysql_connection,*sock=0;
+
+static MYSQL mysql_connection,*sock=0;
static char insert_pat[12 * 1024],*opt_password=0,*current_user=0,
*current_host=0,*path=0,*fields_terminated=0,
*lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
*where=0,
*opt_compatible_mode_str= 0,
*err_ptr= 0;
+static char compatible_mode_normal_str[255];
static char *default_charset= (char*) MYSQL_UNIVERSAL_CLIENT_CHARSET;
static ulong opt_compatible_mode= 0;
static uint opt_mysql_port= 0, err_len= 0;
@@ -111,6 +113,15 @@ const char *compatible_mode_names[]=
"ANSI",
NullS
};
+#define MASK_ANSI_QUOTES \
+(\
+ (1<<2) | /* POSTGRESQL */\
+ (1<<3) | /* ORACLE */\
+ (1<<4) | /* MSSQL */\
+ (1<<5) | /* DB2 */\
+ (1<<6) | /* MAXDB */\
+ (1<<10) /* ANSI */\
+)
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
"", compatible_mode_names};
@@ -377,10 +388,10 @@ static void write_header(FILE *sql_file, char *db_name)
");
}
fprintf(sql_file,
- "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=\"%s\" */;\n",
- path?"":"NO_AUTO_VALUE_ON_ZERO");
+ "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=\"%s%s%s\" */;\n",
+ path?"":"NO_AUTO_VALUE_ON_ZERO",compatible_mode_normal_str[0]==0?"":",",
+ compatible_mode_normal_str);
}
- return;
} /* write_header */
@@ -480,6 +491,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case (int) OPT_COMPATIBLE:
{
char buff[255];
+ char *end= compatible_mode_normal_str;
+ int i;
+ ulong mode;
opt_quoted= 1;
opt_set_names= 1;
@@ -493,6 +507,27 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
fprintf(stderr, "Invalid mode to --compatible: %s\n", buff);
exit(1);
}
+#if !defined(DBUG_OFF)
+ {
+ uint size_for_sql_mode= 0;
+ const char **ptr;
+ for (ptr= compatible_mode_names; *ptr; ptr++)
+ size_for_sql_mode+= strlen(*ptr);
+ size_for_sql_mode+= sizeof(compatible_mode_names)-1;
+ DBUG_ASSERT(sizeof(compatible_mode_normal_str)>=size_for_sql_mode);
+ }
+#endif
+ mode= opt_compatible_mode;
+ for (i= 0, mode= opt_compatible_mode; mode; mode>>= 1, i++)
+ {
+ if (mode & 1)
+ {
+ end= strmov(end, compatible_mode_names[i]);
+ end= strmov(end, ",");
+ }
+ }
+ if (end!=compatible_mode_normal_str)
+ end[-1]= 0;
break;
}
case (int) OPT_MYSQL_PROTOCOL:
@@ -594,6 +629,7 @@ static void safe_exit(int error)
*/
static int dbConnect(char *host, char *user,char *passwd)
{
+ char buff[20+FN_REFLEN];
DBUG_ENTER("dbConnect");
if (verbose)
{
@@ -622,6 +658,16 @@ static int dbConnect(char *host, char *user,char *passwd)
DBerror(&mysql_connection, "when trying to connect");
return 1;
}
+ sprintf(buff, "/*!40100 SET @@SQL_MODE=\"%s\" */",
+ compatible_mode_normal_str);
+ if (mysql_query(sock, buff))
+ {
+ fprintf(stderr, "%s: Can't set the compatible mode %s (error %s)\n",
+ my_progname, compatible_mode_normal_str, mysql_error(sock));
+ mysql_close(sock);
+ safe_exit(EX_MYSQLERR);
+ return 1;
+ }
return 0;
} /* dbConnect */
@@ -670,17 +716,19 @@ static my_bool test_if_special_chars(const char *str)
static char *quote_name(const char *name, char *buff, my_bool force)
{
char *to= buff;
+ char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`';
+
if (!force && !opt_quoted && !test_if_special_chars(name))
return (char*) name;
- *to++= QUOTE_CHAR;
+ *to++= qtype;
while (*name)
{
- if (*name == QUOTE_CHAR)
- *to++= QUOTE_CHAR;
+ if (*name == qtype)
+ *to++= qtype;
*to++= *name++;
}
- to[0]=QUOTE_CHAR;
- to[1]=0;
+ to[0]= qtype;
+ to[1]= 0;
return buff;
} /* quote_name */
@@ -853,31 +901,6 @@ static uint getTableStructure(char *table, char* db)
/* Make an sql-file, if path was given iow. option -T was given */
char buff[20+FN_REFLEN];
- if (opt_compatible_mode)
- {
- char *end;
- uint i;
-
- sprintf(buff, "/*!40100 SET @@sql_mode=\"");
- end= strend(buff);
- for (i= 0; opt_compatible_mode; opt_compatible_mode>>= 1, i++)
- {
- if (opt_compatible_mode & 1)
- {
- end= strmov(end, compatible_mode_names[i]);
- end= strmov(end, ",");
- }
- }
- end= strmov(end-1, "\" */");
- if (mysql_query(sock, buff))
- {
- fprintf(stderr, "%s: Can't set the compatible mode '%s' (%s)\n",
- my_progname, table, mysql_error(sock));
- safe_exit(EX_MYSQLERR);
- DBUG_RETURN(0);
- }
- }
-
sprintf(buff,"show create table %s", result_table);
if (mysql_query(sock, buff))
{
@@ -1858,6 +1881,7 @@ int main(int argc, char **argv)
{
MYSQL_ROW row;
MYSQL_RES *master;
+ compatible_mode_normal_str[0]= 0;
MY_INIT(argv[0]);
if (get_options(&argc, &argv))
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 70dcc874b0f..741da982008 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -109,6 +109,7 @@ MYSQL_MANAGER* manager=0;
static char **default_argv;
static const char *load_default_groups[]= { "mysqltest","client",0 };
+static char line_buffer[MAX_DELIMITER], *line_buffer_pos= line_buffer;;
static FILE* file_stack[MAX_INCLUDE_DEPTH];
static FILE** cur_file;
@@ -128,6 +129,8 @@ static CHARSET_INFO *charset_info= &my_charset_latin1;
static int embedded_server_arg_count=0;
static char *embedded_server_args[MAX_SERVER_ARGS];
+static my_bool display_result_vertically= FALSE;
+
static const char *embedded_server_groups[] = {
"server",
"embedded",
@@ -213,6 +216,8 @@ Q_REQUIRE_VERSION,
Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
Q_ENABLE_INFO, Q_DISABLE_INFO,
Q_EXEC, Q_DELIMITER,
+Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
+Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
@@ -286,6 +291,10 @@ const char *command_names[]=
"disable_info",
"exec",
"delimiter",
+ "vertical_results",
+ "horizontal_results",
+ "query_vertical",
+ "query_horizontal",
0
};
@@ -862,44 +871,59 @@ int do_exec(struct st_query* q)
char buf[1024];
FILE *res_file;
char *cmd= q->first_argument;
+ DBUG_ENTER("do_exec");
while (*cmd && my_isspace(charset_info, *cmd))
cmd++;
if (!*cmd)
die("Missing argument in exec\n");
- if (q->record_file[0])
- {
- init_dynamic_string(&ds_tmp, "", 16384, 65536);
- ds= &ds_tmp;
- }
- else
- ds= &ds_res;
+ DBUG_PRINT("info", ("Executing '%s'", cmd));
if (!(res_file= popen(cmd, "r")) && q->abort_on_error)
die("popen() failed\n");
- while (fgets(buf, sizeof(buf), res_file))
- replace_dynstr_append_mem(ds, buf, strlen(buf));
- pclose(res_file);
-
- if (glob_replace)
- free_replace();
- if (record)
+ if (disable_result_log)
{
- if (!q->record_file[0] && !result_file)
- die("At line %u: Missing result file", start_lineno);
- if (!result_file)
- str_to_file(q->record_file, ds->str, ds->length);
+ while (fgets(buf, sizeof(buf), res_file))
+ {
+ buf[strlen(buf)-1]=0;
+ DBUG_PRINT("exec_result",("%s", buf));
+ }
}
- else if (q->record_file[0])
+ else
{
- error= check_result(ds, q->record_file, q->require_file);
+ if (q->record_file[0])
+ {
+ init_dynamic_string(&ds_tmp, "", 16384, 65536);
+ ds= &ds_tmp;
+ }
+ else
+ ds= &ds_res;
+
+ while (fgets(buf, sizeof(buf), res_file))
+ replace_dynstr_append_mem(ds, buf, strlen(buf));
+
+ if (glob_replace)
+ free_replace();
+
+ if (record)
+ {
+ if (!q->record_file[0] && !result_file)
+ die("At line %u: Missing result file", start_lineno);
+ if (!result_file)
+ str_to_file(q->record_file, ds->str, ds->length);
+ }
+ else if (q->record_file[0])
+ {
+ error= check_result(ds, q->record_file, q->require_file);
+ }
+ if (ds == &ds_tmp)
+ dynstr_free(&ds_tmp);
}
- if (ds == &ds_tmp)
- dynstr_free(&ds_tmp);
+ pclose(res_file);
- return error;
+ DBUG_RETURN(error);
}
int var_query_set(VAR* v, const char* p, const char** p_end)
@@ -1034,7 +1058,7 @@ int do_system(struct st_query* q)
eval_expr(&v, p, 0); /* NULL terminated */
if (v.str_val_len)
{
- char expr_buf[512];
+ char expr_buf[1024];
if ((uint)v.str_val_len > sizeof(expr_buf) - 1)
v.str_val_len = sizeof(expr_buf) - 1;
memcpy(expr_buf, v.str_val, v.str_val_len);
@@ -1628,24 +1652,49 @@ int do_while(struct st_query* q)
}
-my_bool end_of_query(int c, char* p)
+/*
+ Read characters from line buffer or file. This is needed to allow
+ my_ungetc() to buffer MAX_DELIMITER characters for a file
+
+ NOTE:
+ This works as long as one doesn't change files (with 'source file_name')
+ when there is things pushed into the buffer. This should however not
+ happen for any tests in the test suite.
+*/
+
+int my_getc(FILE *file)
+{
+ if (line_buffer_pos == line_buffer)
+ return fgetc(file);
+ return *--line_buffer_pos;
+}
+
+void my_ungetc(int c)
+{
+ *line_buffer_pos++= (char) c;
+}
+
+
+my_bool end_of_query(int c)
{
- uint i, j;
- int tmp[MAX_DELIMITER]= {0};
+ uint i,j;
+ char tmp[MAX_DELIMITER];
+
+ if (c != *delimiter)
+ return 0;
- for (i= 0; c == *(delimiter + i) && i < delimiter_length;
- i++, c= fgetc(*cur_file))
+ for (i= 1; i < delimiter_length &&
+ (c= my_getc(*cur_file)) == *(delimiter + i);
+ i++)
tmp[i]= c;
- tmp[i]= c;
- for (j= i; j > 0 && i != delimiter_length; j--)
- ungetc(tmp[j], *cur_file);
if (i == delimiter_length)
- {
- ungetc(tmp[i], *cur_file);
- *p= 0;
- return 1;
- }
+ return 1; /* Found delimiter */
+
+ /* didn't find delimiter, push back things that we read */
+ my_ungetc(c);
+ while (i > 1)
+ my_ungetc(tmp[--i]);
return 0;
}
@@ -1663,7 +1712,7 @@ int read_line(char* buf, int size)
for (; p < buf_end ;)
{
no_save= 0;
- c= fgetc(*cur_file);
+ c= my_getc(*cur_file);
if (feof(*cur_file))
{
if ((*cur_file) != stdin)
@@ -1678,8 +1727,11 @@ int read_line(char* buf, int size)
switch(state) {
case R_NORMAL:
/* Only accept '{' in the beginning of a line */
- if (end_of_query(c, p))
+ if (end_of_query(c))
+ {
+ *p= 0;
return 0;
+ }
else if (c == '\'')
state = R_Q1;
else if (c == '"')
@@ -1715,7 +1767,7 @@ int read_line(char* buf, int size)
*buf= 0;
return 0;
}
- else if (end_of_query(c, p) || c == '{')
+ else if (end_of_query(c) || c == '{')
{
*p= 0;
return 0;
@@ -1735,8 +1787,11 @@ int read_line(char* buf, int size)
state= R_ESC_SLASH_Q1;
break;
case R_ESC_Q_Q1:
- if (end_of_query(c, p))
+ if (end_of_query(c))
+ {
+ *p= 0;
return 0;
+ }
if (c != '\'')
state= R_NORMAL;
else
@@ -1753,8 +1808,11 @@ int read_line(char* buf, int size)
state= R_ESC_SLASH_Q2;
break;
case R_ESC_Q_Q2:
- if (end_of_query(c, p))
+ if (end_of_query(c))
+ {
+ *p= 0;
return 0;
+ }
if (c != '"')
state= R_NORMAL;
else
@@ -1779,11 +1837,12 @@ int read_query(struct st_query** q_ptr)
char *p = read_query_buf, * p1 ;
int expected_errno;
struct st_query* q;
+ DBUG_ENTER("read_query_buf");
if (parser.current_line < parser.read_lines)
{
get_dynamic(&q_lines, (gptr) q_ptr, parser.current_line) ;
- return 0;
+ DBUG_RETURN(0);
}
if (!(*q_ptr= q= (struct st_query*) my_malloc(sizeof(*q), MYF(MY_WME))) ||
insert_dynamic(&q_lines, (gptr) &q))
@@ -1802,7 +1861,7 @@ int read_query(struct st_query** q_ptr)
q->type = Q_UNKNOWN;
q->query_buf= q->query= 0;
if (read_line(read_query_buf, sizeof(read_query_buf)))
- return 1;
+ DBUG_RETURN(1);
if (*p == '#')
{
@@ -1856,7 +1915,7 @@ int read_query(struct st_query** q_ptr)
q->first_argument= p;
q->end= strend(q->query);
parser.read_lines++;
- return 0;
+ DBUG_RETURN(0);
}
@@ -1894,7 +1953,7 @@ static struct my_option my_long_options[] =
{"password", 'p', "Password to use when connecting to server.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection.", (gptr*) &port,
- (gptr*) &port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0},
{"quiet", 's', "Suppress all normal output.", (gptr*) &silent,
(gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"record", 'r', "Record output of test_file into result file.",
@@ -2110,6 +2169,7 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
{
MYSQL_ROW row;
uint num_fields= mysql_num_fields(res);
+ MYSQL_FIELD *fields= !display_result_vertically ? 0 : mysql_fetch_fields(res);
unsigned long *lengths;
while ((row = mysql_fetch_row(res)))
{
@@ -2130,11 +2190,22 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
val= "NULL";
len= 4;
}
- if (i)
+ if (!display_result_vertically)
+ {
+ if (i)
+ dynstr_append_mem(ds, "\t", 1);
+ replace_dynstr_append_mem(ds, val, len);
+ }
+ else
+ {
+ dynstr_append(ds, fields[i].name);
dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, val, len);
+ replace_dynstr_append_mem(ds, val, len);
+ dynstr_append_mem(ds, "\n", 1);
+ }
}
- dynstr_append_mem(ds, "\n", 1);
+ if (!display_result_vertically)
+ dynstr_append_mem(ds, "\n", 1);
}
free_replace_column();
}
@@ -2276,16 +2347,20 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
{
if (res)
{
- int num_fields= mysql_num_fields(res);
- MYSQL_FIELD *fields= mysql_fetch_fields(res);
- for (i = 0; i < num_fields; i++)
+ if (!display_result_vertically)
{
- if (i)
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append(ds, fields[i].name);
+ int num_fields= mysql_num_fields(res);
+ MYSQL_FIELD *fields= mysql_fetch_fields(res);
+ for (i = 0; i < num_fields; i++)
+ {
+ if (i)
+ dynstr_append_mem(ds, "\t", 1);
+ replace_dynstr_append_mem(ds, fields[i].name,
+ strlen(fields[i].name));
+ }
+ dynstr_append_mem(ds, "\n", 1);
}
- dynstr_append_mem(ds, "\n", 1);
append_result(ds, res);
}
@@ -2308,17 +2383,20 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
mysql_free_result(warn_res);
}
}
- if (!disable_info && mysql_info(mysql))
+ if (!disable_info)
{
- dynstr_append(ds, "info: ");
- dynstr_append(ds, mysql_info(mysql));
- dynstr_append_mem(ds, "\n", 1);
+ char buf[40];
+ sprintf(buf,"affected rows: %lu\n",(ulong) mysql_affected_rows(mysql));
+ dynstr_append(ds, buf);
+ if (mysql_info(mysql))
+ {
+ dynstr_append(ds, "info: ");
+ dynstr_append(ds, mysql_info(mysql));
+ dynstr_append_mem(ds, "\n", 1);
+ }
}
}
- if (glob_replace)
- free_replace();
-
if (record)
{
if (!q->record_file[0] && !result_file)
@@ -2339,6 +2417,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
mysql_error(mysql);
end:
+ free_replace();
last_result=0;
if (ds == &ds_tmp)
dynstr_free(&ds_tmp);
@@ -2352,10 +2431,12 @@ void get_query_type(struct st_query* q)
{
char save;
uint type;
+ DBUG_ENTER("get_query_type");
+
if (*q->query == '}')
{
q->type = Q_END_BLOCK;
- return;
+ DBUG_VOID_RETURN;
}
if (q->type != Q_COMMENT_WITH_COMMAND)
q->type = Q_QUERY;
@@ -2366,8 +2447,10 @@ void get_query_type(struct st_query* q)
q->query[q->first_word_len]=save;
if (type > 0)
q->type=(enum enum_commands) type; /* Found command */
+ DBUG_VOID_RETURN;
}
+
static byte *get_var_key(const byte* var, uint* len,
my_bool __attribute__((unused)) t)
{
@@ -2557,12 +2640,33 @@ int main(int argc, char **argv)
strmake(delimiter, q->first_argument, sizeof(delimiter) - 1);
delimiter_length= strlen(delimiter);
break;
+ case Q_DISPLAY_VERTICAL_RESULTS: display_result_vertically= TRUE; break;
+ case Q_DISPLAY_HORIZONTAL_RESULTS:
+ display_result_vertically= FALSE; break;
case Q_LET: do_let(q); break;
case Q_EVAL_RESULT: eval_result = 1; break;
case Q_EVAL:
if (q->query == q->query_buf)
q->query= q->first_argument;
/* fall through */
+ case Q_QUERY_VERTICAL:
+ case Q_QUERY_HORIZONTAL:
+ {
+ my_bool old_display_result_vertically= display_result_vertically;
+ if (!q->query[q->first_word_len])
+ {
+ /* This happens when we use 'query_..' on it's own line */
+ q_send_flag=1;
+ break;
+ }
+ /* fix up query pointer if this is * first iteration for this line */
+ if (q->query == q->query_buf)
+ q->query += q->first_word_len + 1;
+ display_result_vertically= (q->type==Q_QUERY_VERTICAL);
+ error |= run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND);
+ display_result_vertically= old_display_result_vertically;
+ break;
+ }
case Q_QUERY:
case Q_REAP:
{
diff --git a/configure.in b/configure.in
index 6165702a86d..de546d9c078 100644
--- a/configure.in
+++ b/configure.in
@@ -1013,7 +1013,7 @@ case $SYSTEM_TYPE in
*darwin5*)
if test "$ac_cv_prog_gcc" = "yes"
then
- 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"
+ FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH"
CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O"
@@ -1023,7 +1023,7 @@ case $SYSTEM_TYPE in
*darwin6*)
if test "$ac_cv_prog_gcc" = "yes"
then
- FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
+ FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH"
CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O"
@@ -1032,7 +1032,7 @@ case $SYSTEM_TYPE in
*darwin7*)
if test "$ac_cv_prog_gcc" = "yes"
then
- FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE"
+ FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ"
CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O"
@@ -1839,7 +1839,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \
- mkstemp mlockall perror poll pread pthread_attr_create \
+ mkstemp mlockall perror poll pread pthread_attr_create clock_gettime \
pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \
pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
@@ -2706,7 +2706,7 @@ then
esac
(cd $bdb/build_unix && \
sh $rel_srcdir/$bdb/dist/configure $bdb_conf_flags) || \
- AC_MSG_ERROR([could not configure Berkeley DB])
+ AC_MSG_ERROR([could not configure Berkeley DB])
dnl echo "bdb = '$bdb'; inc = '$bdb_includes', lib = '$bdb_libs'"
echo "END OF BERKELEY DB CONFIGURATION"
@@ -2745,25 +2745,7 @@ EOF
then
innodb_conf_flags=""
sql_server_dirs="$sql_server_dirs innobase"
- echo "CONFIGURING FOR INNODB"
- if test ! -d "innobase"; then
- # This should only happen when doing a VPATH build
- echo "NOTICE: I have to make the Innobase directory: `pwd`/innobase"
- mkdir "innobase" || exit 1
- fi
- rel_srcdir=
- case "$srcdir" in
- /* ) rel_srcdir="$srcdir" ;;
- * ) rel_srcdir="../$srcdir" ;;
- esac
- if test "x$enable_dependency_tracking" == xno
- then
- innodb_conf_flags=--disable-dependency-tracking
- fi
- (cd innobase && sh $rel_srcdir/innobase/configure --host=$host $innodb_conf_flags) \
- || AC_MSG_ERROR([could not configure INNODB])
-
- echo "END OF INNODB CONFIGURATION"
+ AC_CONFIG_SUBDIRS(innobase)
fi
#
# END of configuration for optional table handlers
diff --git a/extra/replace.c b/extra/replace.c
index 8e007e3a971..a44c33a4694 100644
--- a/extra/replace.c
+++ b/extra/replace.c
@@ -14,12 +14,16 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Replace strings in textfile
- This program replace strings in a file or on stdin/stdout.
- It accepts a list of from-strings and to-strings and replaces all
- occurents of from-strings to to-strings.
- The first occurents of a found string is matched. If there are more than
- one possibly replace the longer from-string is replaced.
+/*
+ Replace strings in textfile
+
+ This program replaces strings in files or from stdin to stdout.
+ It accepts a list of from-string/to-string pairs and replaces
+ each occurrence of a from-string with the corresponding to-string.
+ The first occurrence of a found string is matched. If there is more
+ than one possibility for the string to replace, longer matches
+ are preferred before shorter matches.
+
Special characters in from string:
\^ Match start of line.
\$ Match end of line.
@@ -167,7 +171,7 @@ register char **argv[];
break;
case '#':
DBUG_PUSH (++pos);
- pos= (char*) " "; /* Skipp rest of arguments */
+ pos= (char*) " "; /* Skip rest of arguments */
break;
case 'V':
version=1;
@@ -179,12 +183,13 @@ register char **argv[];
if (version)
break;
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
- puts("This program replace strings in a file or on stdin/stdout.\n"
- "It accepts a list of from-strings and to-strings and replaces\n"
- "all occurents of from-strings to to-strings.\n"
- "The first occurents of a found string is matched. Longer matches\n"
- "are prefered before shorter matches.\n\n"
- "Special characters in from string:\n"
+ puts("This program replaces strings in files or from stdin to stdout.\n"
+ "It accepts a list of from-string/to-string pairs and replaces\n"
+ "each occurrence of a from-string with the corresponding to-string.\n"
+ "The first occurrence of a found string is matched. If there is\n"
+ "more than one possibility for the string to replace, longer\n"
+ "matches are preferred before shorter matches.\n\n"
+ "A from-string can contain these special characters:\n"
" \\^ Match start of line.\n"
" \\$ Match end of line.\n"
" \\b Match space-character, start of line or end of line.\n"
@@ -237,7 +242,7 @@ POINTER_ARRAY *from_array,*to_array;
(*argv)++;
}
if (*argc)
- { /* Skipp "--" argument */
+ { /* Skip "--" argument */
(*argc)--;
(*argv)++;
}
@@ -949,9 +954,11 @@ static void free_buffer()
}
-/* Fill the buffer retaining the last n bytes at the beginning of the
- newly filled buffer (for backward context). Returns the number of new
- bytes read from disk. */
+/*
+ Fill the buffer retaining the last n bytes at the beginning of the
+ newly filled buffer (for backward context). Returns the number of new
+ bytes read from disk.
+*/
static int fill_buffer_retaining(fd,n)
File fd;
diff --git a/heap/hp_delete.c b/heap/hp_delete.c
index 89d685b7d0b..c918cf37f05 100644
--- a/heap/hp_delete.c
+++ b/heap/hp_delete.c
@@ -60,9 +60,11 @@ err:
DBUG_RETURN(my_errno);
}
+
/*
-Remove one key from rb-tree
+ Remove one key from rb-tree
*/
+
int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
const byte *record, byte *recpos, int flag)
{
@@ -82,11 +84,25 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
return res;
}
- /* Remove one key from hash-table */
- /* Flag is set if we want's to correct info->current_ptr */
+
+/*
+ Remove one key from hash-table
+
+ SYNPOSIS
+ hp_delete_key()
+ info Hash handler
+ keyinfo key definition of key that we want to delete
+ record row data to be deleted
+ recpos Pointer to heap record in memory
+ flag Is set if we want's to correct info->current_ptr
+
+ RETURN
+ 0 ok
+ # error number
+*/
int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
- const byte *record, byte *recpos, int flag)
+ const byte *record, byte *recpos, int flag)
{
ulong blength,pos2,pos_hashnr,lastpos_hashnr;
HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
diff --git a/heap/hp_extra.c b/heap/hp_extra.c
index 46e3f529f34..dd41d6c5f19 100644
--- a/heap/hp_extra.c
+++ b/heap/hp_extra.c
@@ -21,6 +21,10 @@
#include "heapdef.h"
+static void heap_extra_keyflag(register HP_INFO *info,
+ enum ha_extra_function function);
+
+
/* set extra flags for database */
int heap_extra(register HP_INFO *info, enum ha_extra_function function)
@@ -41,8 +45,37 @@ int heap_extra(register HP_INFO *info, enum ha_extra_function function)
case HA_EXTRA_READCHECK:
info->opt_flag|= READ_CHECK_USED;
break;
+ case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
+ case HA_EXTRA_CHANGE_KEY_TO_DUP:
+ heap_extra_keyflag(info, function);
+ break;
default:
break;
}
DBUG_RETURN(0);
} /* heap_extra */
+
+
+/*
+ Start/Stop Inserting Duplicates Into a Table, WL#1648.
+ */
+static void heap_extra_keyflag(register HP_INFO *info,
+ enum ha_extra_function function)
+{
+ uint idx;
+
+ for (idx= 0; idx< info->s->keys; idx++)
+ {
+ switch (function) {
+ case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
+ info->s->keydef[idx].flag|= HA_NOSAME;
+ break;
+ case HA_EXTRA_CHANGE_KEY_TO_DUP:
+ info->s->keydef[idx].flag&= ~(HA_NOSAME);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
diff --git a/include/config-win.h b/include/config-win.h
index abc1aa7a6ee..518f445861a 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -95,6 +95,7 @@ functions */
#define LONGLONG_MAX ((__int64) 0x7FFFFFFFFFFFFFFF)
#define ULONGLONG_MAX ((unsigned __int64) 0xFFFFFFFFFFFFFFFF)
#define LL(A) ((__int64) A)
+#define ULL(A) ((unsigned __int64) A)
/* Type information */
diff --git a/include/errmsg.h b/include/errmsg.h
index 8f3ddfa9796..140ff531248 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -63,27 +63,30 @@ extern const char *client_errors[]; /* Error messages */
#define CR_PROBE_MASTER_CONNECT 2025
#define CR_SSL_CONNECTION_ERROR 2026
#define CR_MALFORMED_PACKET 2027
+#define CR_WRONG_LICENSE 2028
/* new 4.1 error codes */
-#define CR_NULL_POINTER 2028
-#define CR_NO_PREPARE_STMT 2029
-#define CR_NOT_ALL_PARAMS_BOUND 2030
-#define CR_DATA_TRUNCATED 2031
-#define CR_NO_PARAMETERS_EXISTS 2032
-#define CR_INVALID_PARAMETER_NO 2033
-#define CR_INVALID_BUFFER_USE 2034
-#define CR_UNSUPPORTED_PARAM_TYPE 2035
+#define CR_NULL_POINTER 2029
+#define CR_NO_PREPARE_STMT 2030
+#define CR_PARAMS_NOT_BOUND 2031
+#define CR_DATA_TRUNCATED 2032
+#define CR_NO_PARAMETERS_EXISTS 2033
+#define CR_INVALID_PARAMETER_NO 2034
+#define CR_INVALID_BUFFER_USE 2035
+#define CR_UNSUPPORTED_PARAM_TYPE 2036
-#define CR_SHARED_MEMORY_CONNECTION 2036
-#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2037
-#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2038
-#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2039
-#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2040
-#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2041
-#define CR_SHARED_MEMORY_MAP_ERROR 2042
-#define CR_SHARED_MEMORY_EVENT_ERROR 2043
-#define CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR 2044
-#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2045
-#define CR_CONN_UNKNOW_PROTOCOL 2046
-#define CR_INVALID_CONN_HANDLE 2047
-#define CR_SECURE_AUTH 2048
+#define CR_SHARED_MEMORY_CONNECTION 2037
+#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2038
+#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2039
+#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2040
+#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2041
+#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2042
+#define CR_SHARED_MEMORY_MAP_ERROR 2043
+#define CR_SHARED_MEMORY_EVENT_ERROR 2044
+#define CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR 2045
+#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046
+#define CR_CONN_UNKNOW_PROTOCOL 2047
+#define CR_INVALID_CONN_HANDLE 2048
+#define CR_SECURE_AUTH 2049
+#define CR_FETCH_CANCELLED 2050
+#define CR_NO_DATA 2051
diff --git a/include/m_ctype.h b/include/m_ctype.h
index a97d25862bd..328359125f4 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -210,7 +210,8 @@ typedef struct charset_info_st
uint strxfrm_multiply;
uint mbminlen;
uint mbmaxlen;
- char max_sort_char; /* For LIKE optimization */
+ uint16 min_sort_char;
+ uint16 max_sort_char; /* For LIKE optimization */
MY_CHARSET_HANDLER *cset;
MY_COLLATION_HANDLER *coll;
@@ -305,6 +306,13 @@ my_bool my_like_range_simple(CHARSET_INFO *cs,
char *min_str, char *max_str,
uint *min_length, uint *max_length);
+my_bool my_like_range_ucs2(CHARSET_INFO *cs,
+ const char *ptr, uint ptr_length,
+ pbool escape, pbool w_one, pbool w_many,
+ uint res_length,
+ char *min_str, char *max_str,
+ uint *min_length, uint *max_length);
+
int my_wildcmp_8bit(CHARSET_INFO *,
const char *str,const char *str_end,
@@ -340,23 +348,14 @@ uint my_instr_mb(struct charset_info_st *,
extern my_bool my_parse_charset_xml(const char *bug, uint len,
int (*add)(CHARSET_INFO *cs));
-#undef _U
-#undef _L
-#undef _NMR
-#undef _SPC
-#undef _PNT
-#undef _CTR
-#undef _B
-#undef _X
-
-#define _U 01 /* Upper case */
-#define _L 02 /* Lower case */
-#define _NMR 04 /* Numeral (digit) */
-#define _SPC 010 /* Spacing character */
-#define _PNT 020 /* Punctuation */
-#define _CTR 040 /* Control character */
-#define _B 0100 /* Blank */
-#define _X 0200 /* heXadecimal digit */
+#define _MY_U 01 /* Upper case */
+#define _MY_L 02 /* Lower case */
+#define _MY_NMR 04 /* Numeral (digit) */
+#define _MY_SPC 010 /* Spacing character */
+#define _MY_PNT 020 /* Punctuation */
+#define _MY_CTR 040 /* Control character */
+#define _MY_B 0100 /* Blank */
+#define _MY_X 0200 /* heXadecimal digit */
#define my_isascii(c) (!((c) & ~0177))
@@ -365,17 +364,17 @@ extern my_bool my_parse_charset_xml(const char *bug, uint len,
#define my_toprint(c) ((c) | 64)
#define my_toupper(s,c) (char) ((s)->to_upper[(uchar) (c)])
#define my_tolower(s,c) (char) ((s)->to_lower[(uchar) (c)])
-#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_U | _L))
-#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _U)
-#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _L)
-#define my_isdigit(s, c) (((s)->ctype+1)[(uchar) (c)] & _NMR)
-#define my_isxdigit(s, c) (((s)->ctype+1)[(uchar) (c)] & _X)
-#define my_isalnum(s, c) (((s)->ctype+1)[(uchar) (c)] & (_U | _L | _NMR))
-#define my_isspace(s, c) (((s)->ctype+1)[(uchar) (c)] & _SPC)
-#define my_ispunct(s, c) (((s)->ctype+1)[(uchar) (c)] & _PNT)
-#define my_isprint(s, c) (((s)->ctype+1)[(uchar) (c)] & (_PNT | _U | _L | _NMR | _B))
-#define my_isgraph(s, c) (((s)->ctype+1)[(uchar) (c)] & (_PNT | _U | _L | _NMR))
-#define my_iscntrl(s, c) (((s)->ctype+1)[(uchar) (c)] & _CTR)
+#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L))
+#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_U)
+#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_L)
+#define my_isdigit(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_NMR)
+#define my_isxdigit(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_X)
+#define my_isalnum(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L | _MY_NMR))
+#define my_isspace(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_SPC)
+#define my_ispunct(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_PNT)
+#define my_isprint(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR | _MY_B))
+#define my_isgraph(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR))
+#define my_iscntrl(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_CTR)
/* Some macros that should be cleaned up a little */
#define my_isvar(s,c) (my_isalnum(s,c) || (c) == '_')
diff --git a/include/my_base.h b/include/my_base.h
index 89b46de520f..d23a70b8a55 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -28,6 +28,11 @@
#include <my_sys.h>
#include <m_string.h>
#include <errno.h>
+
+#ifndef EOVERFLOW
+#define EOVERFLOW 84
+#endif
+
#ifdef MSDOS
#include <share.h> /* Neaded for sopen() */
#endif
@@ -126,13 +131,22 @@ enum ha_extra_function {
HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/
HA_EXTRA_NO_IGNORE_DUP_KEY,
/*
- Instructs InnoDB to retrieve all columns, not just those where
- field->query_id is the same as the current query id
+ Instructs InnoDB to retrieve all columns (except in key read), not just
+ those where field->query_id is the same as the current query id
*/
HA_EXTRA_RETRIEVE_ALL_COLS,
+ /*
+ Instructs InnoDB to retrieve at least all the primary key columns
+ */
+ HA_EXTRA_RETRIEVE_PRIMARY_KEY,
HA_EXTRA_PREPARE_FOR_DELETE,
HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */
- HA_EXTRA_PRELOAD_BUFFER_SIZE /* Set buffer size for preloading */
+ HA_EXTRA_PRELOAD_BUFFER_SIZE, /* Set buffer size for preloading */
+ /*
+ On-the-fly switching between unique and non-unique key inserting.
+ */
+ HA_EXTRA_CHANGE_KEY_TO_UNIQUE,
+ HA_EXTRA_CHANGE_KEY_TO_DUP
};
/* The following is parameter to ha_panic() */
diff --git a/include/my_global.h b/include/my_global.h
index a8078f579ee..4a56741ddbc 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -692,7 +692,7 @@ typedef long long my_ptrdiff_t;
#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
/* Size to make adressable obj. */
#define ALIGN_PTR(A, t) ((t*) MY_ALIGN((A),sizeof(t)))
- /* Offset of filed f in structure t */
+ /* Offset of field f in structure t */
#define OFFSET(t, f) ((size_t)(char *)&((t *)0)->f)
#define ADD_TO_PTR(ptr,size,type) (type) ((byte*) (ptr)+size)
#define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((byte*) (A) - (byte*) (B))
@@ -842,6 +842,14 @@ typedef char bool; /* Ordinary boolean values 0 1 */
#endif
#endif
+#ifndef ULL
+#ifdef HAVE_LONG_LONG
+#define ULL(A) A ## ULL
+#else
+#define ULL(A) A ## UL
+#endif
+#endif
+
/*
Defines to make it possible to prioritize register assignments. No
longer that important with modern compilers.
diff --git a/include/my_sys.h b/include/my_sys.h
index 6547022601d..a97ddcce40d 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -606,7 +606,7 @@ extern void pack_dirname(my_string to,const char *from);
extern uint unpack_dirname(my_string to,const char *from);
extern uint cleanup_dirname(my_string to,const char *from);
extern uint system_filename(my_string to,const char *from);
-extern my_string unpack_filename(my_string to,const char *from);
+extern uint unpack_filename(my_string to,const char *from);
extern my_string intern_filename(my_string to,const char *from);
extern my_string directory_file_name(my_string dst, const char *src);
extern int pack_filename(my_string to, const char *name, size_s max_length);
@@ -663,9 +663,9 @@ extern int my_b_safe_write(IO_CACHE *info,const byte *Buffer,uint Count);
extern int my_block_write(IO_CACHE *info, const byte *Buffer,
uint Count, my_off_t pos);
-extern int _flush_io_cache(IO_CACHE *info, int need_append_buffer_lock);
+extern int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock);
-#define flush_io_cache(info) _flush_io_cache((info),1)
+#define flush_io_cache(info) my_b_flush_io_cache((info),1)
extern int end_io_cache(IO_CACHE *info);
extern uint my_b_fill(IO_CACHE *info);
@@ -714,6 +714,7 @@ extern void my_free_lock(byte *ptr,myf flags);
#define my_free_lock(A,B) my_free((A),(B))
#endif
#define alloc_root_inited(A) ((A)->min_malloc != 0)
+#define clear_alloc_root(A) bzero((void *) (A), sizeof(MEM_ROOT))
extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size);
extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size);
@@ -739,6 +740,7 @@ extern ulong crc32(ulong crc, const uchar *buf, uint len);
extern uint my_set_max_open_files(uint files);
void my_free_open_file_info(void);
+ulonglong my_getsystime(void);
my_bool my_gethwaddr(uchar *to);
/* character sets */
diff --git a/include/my_tree.h b/include/my_tree.h
index 0e705e19bba..14d8593b6dc 100644
--- a/include/my_tree.h
+++ b/include/my_tree.h
@@ -22,7 +22,9 @@ extern "C" {
#include "my_base.h" /* get 'enum ha_rkey_function' */
-#define MAX_TREE_HEIGHT 40 /* = max 1048576 leafs in tree */
+/* Worst case tree is half full. This gives use 2^(MAX_TREE_HEIGHT/2) leafs */
+#define MAX_TREE_HEIGHT 64
+
#define ELEMENT_KEY(tree,element)\
(tree->offset_to_key ? (void*)((byte*) element+tree->offset_to_key) :\
*((void**) (element+1)))
diff --git a/include/mysql.h b/include/mysql.h
index 5b3037d9261..e14381a94de 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -77,6 +77,8 @@ extern char *mysql_unix_port;
#define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG)
#define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR)
+#define HAVE_DEPRECATED_411_API 1
+
typedef struct st_mysql_field {
char *name; /* Name of column */
char *org_name; /* Original column name, if an alias */
@@ -254,6 +256,11 @@ typedef struct st_mysql
LIST *stmts; /* list of all statements */
const struct st_mysql_methods *methods;
void *thd;
+ /*
+ Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag
+ from mysql_stmt_close if close had to cancel result set of this object.
+ */
+ my_bool *unbuffered_fetch_owner;
} MYSQL;
typedef struct st_mysql_res {
@@ -268,6 +275,8 @@ typedef struct st_mysql_res {
MYSQL_ROW row; /* If unbuffered read */
MYSQL_ROW current_row; /* buffer to current row */
my_bool eof; /* Used by mysql_fetch_row */
+ /* mysql_stmt_close() had to cancel this result */
+ my_bool unbuffered_fetch_cancelled;
const struct st_mysql_methods *methods;
} MYSQL_RES;
@@ -477,7 +486,11 @@ my_bool STDCALL mysql_read_query_result(MYSQL *mysql);
*/
/* statement state */
-enum PREP_STMT_STATE { MY_ST_UNKNOWN, MY_ST_PREPARE, MY_ST_EXECUTE };
+enum enum_mysql_stmt_state
+{
+ MYSQL_STMT_INIT_DONE= 1, MYSQL_STMT_PREPARE_DONE, MYSQL_STMT_EXECUTE_DONE,
+ MYSQL_STMT_FETCH_DONE
+};
/*
client TIME structure to handle TIME, DATE and TIMESTAMP directly in
@@ -523,31 +536,34 @@ typedef struct st_mysql_bind
/* statement handler */
typedef struct st_mysql_stmt
{
- MYSQL *mysql; /* connection handle */
- MYSQL_BIND *params; /* input parameters */
- MYSQL_RES *result; /* resultset */
- MYSQL_BIND *bind; /* row binding */
- MYSQL_FIELD *fields; /* prepare meta info */
+ MEM_ROOT mem_root; /* root allocations */
LIST list; /* list to keep track of all stmts */
- unsigned char *current_row; /* unbuffered row */
- unsigned char *last_fetched_buffer; /* last fetched column buffer */
- char *query; /* query buffer */
- MEM_ROOT mem_root; /* root allocations */
- my_ulonglong last_fetched_column; /* last fetched column */
+ MYSQL *mysql; /* connection handle */
+ MYSQL_BIND *params; /* input parameters */
+ MYSQL_BIND *bind; /* output parameters */
+ MYSQL_FIELD *fields; /* result set metadata */
+ MYSQL_RES *result; /* cached result set */
/* copy of mysql->affected_rows after statement execution */
my_ulonglong affected_rows;
+ /*
+ mysql_stmt_fetch() calls this function to fetch one row (it's different
+ for buffered, unbuffered and cursor fetch).
+ */
+ int (*read_row_func)(struct st_mysql_stmt *stmt,
+ unsigned char **row);
unsigned long stmt_id; /* Id for prepared statement */
unsigned int last_errno; /* error code */
- unsigned int param_count; /* parameters count */
- unsigned int field_count; /* fields count */
- enum PREP_STMT_STATE state; /* statement state */
+ unsigned int param_count; /* inpute parameters count */
+ unsigned int field_count; /* number of columns in result set */
+ enum enum_mysql_stmt_state state; /* statement state */
char last_error[MYSQL_ERRMSG_SIZE]; /* error message */
char sqlstate[SQLSTATE_LENGTH+1];
- my_bool long_alloced; /* flag to indicate long alloced */
- my_bool send_types_to_server; /* Types sent to server */
- my_bool param_buffers; /* param bound buffers */
- my_bool res_buffers; /* output bound buffers */
- my_bool result_buffered; /* Results buffered */
+ /* Types of input parameters should be sent to server */
+ my_bool send_types_to_server;
+ my_bool bind_param_done; /* input buffers were supplied */
+ my_bool bind_result_done; /* output buffers were supplied */
+ /* mysql_stmt_close() had to cancel this result */
+ my_bool unbuffered_fetch_cancelled;
} MYSQL_STMT;
@@ -573,46 +589,66 @@ typedef struct st_mysql_methods
MYSQL_DATA *(*read_binary_rows)(MYSQL_STMT *stmt);
int (*unbuffered_fetch)(MYSQL *mysql, char **row);
void (*free_embedded_thd)(MYSQL *mysql);
- const char *(*read_statistic)(MYSQL *mysql);
- int (*next_result)(MYSQL *mysql);
+ const char *(*read_statistics)(MYSQL *mysql);
+ my_bool (*next_result)(MYSQL *mysql);
int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
#endif
} MYSQL_METHODS;
+#ifdef HAVE_DEPRECATED_411_API
+/* Deprecated calls (since MySQL 4.1.2) */
+
+/* Use mysql_stmt_init + mysql_stmt_prepare instead */
MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query,
unsigned long length);
-int STDCALL mysql_execute(MYSQL_STMT * stmt);
-unsigned long STDCALL mysql_param_count(MYSQL_STMT * stmt);
-my_bool STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
-my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+#define mysql_execute mysql_stmt_execute
+#define mysql_fetch mysql_stmt_fetch
+#define mysql_fetch_column mysql_stmt_fetch_column
+#define mysql_bind_param mysql_stmt_bind_param
+#define mysql_bind_result mysql_stmt_bind_result
+#define mysql_param_count mysql_stmt_param_count
+#define mysql_param_result mysql_stmt_param_metadata
+#define mysql_get_metadata mysql_stmt_result_metadata
+#define mysql_send_long_data mysql_stmt_send_long_data
+
+#endif /* HAVE_DEPRECATED_411_API */
+
+MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql);
+int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
+ unsigned long length);
+int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
+ unsigned int column,
+ unsigned long offset);
+int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt);
+unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt);
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt);
+my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt,
+ unsigned int param_number,
+ const char *data,
+ unsigned long length);
+MYSQL_RES *STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt);
+MYSQL_RES *STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt);
unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt);
-my_bool STDCALL mysql_commit(MYSQL * mysql);
-my_bool STDCALL mysql_rollback(MYSQL * mysql);
-my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
-int STDCALL mysql_fetch(MYSQL_STMT *stmt);
-int STDCALL mysql_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
- unsigned int column,
- unsigned long offset);
-my_bool STDCALL mysql_send_long_data(MYSQL_STMT *stmt,
- unsigned int param_number,
- const char *data,
- unsigned long length);
-MYSQL_RES *STDCALL mysql_get_metadata(MYSQL_STMT *stmt);
-MYSQL_RES *STDCALL mysql_param_result(MYSQL_STMT *stmt);
-my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
-int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt);
-my_bool STDCALL mysql_more_results(MYSQL *mysql);
-int STDCALL mysql_next_result(MYSQL *mysql);
MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt,
MYSQL_ROW_OFFSET offset);
MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt);
void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset);
my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt);
+my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
+
+my_bool STDCALL mysql_commit(MYSQL * mysql);
+my_bool STDCALL mysql_rollback(MYSQL * mysql);
+my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
+my_bool STDCALL mysql_more_results(MYSQL *mysql);
+int STDCALL mysql_next_result(MYSQL *mysql);
void STDCALL mysql_close(MYSQL *sock);
diff --git a/include/mysql_version.h.in b/include/mysql_version.h.in
index 095531d527d..c440c1298d4 100644
--- a/include/mysql_version.h.in
+++ b/include/mysql_version.h.in
@@ -23,4 +23,9 @@
/* mysqld compile time options */
#endif /* _CUSTOMCONFIG_ */
+
+#ifndef LICENSE
+#define LICENSE "GPL"
+#endif /* LICENSE */
+
#endif /* _mysql_version_h */
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index e95a35bdc51..77164e637cb 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -307,4 +307,6 @@
#define ER_NON_UPDATABLE_TABLE 1288
#define ER_FEATURE_DISABLED 1289
#define ER_OPTION_PREVENTS_STATEMENT 1290
-#define ER_ERROR_MESSAGES 291
+#define ER_DUPLICATED_VALUE_IN_TYPE 1291
+#define ER_TRUNCATED_WRONG_VALUE 1292
+#define ER_ERROR_MESSAGES 293
diff --git a/include/sql_common.h b/include/sql_common.h
index fef573f7450..3f50008a922 100644
--- a/include/sql_common.h
+++ b/include/sql_common.h
@@ -25,6 +25,7 @@ extern "C" {
MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
my_bool default_value, uint server_capabilities);
void free_rows(MYSQL_DATA *cur);
+void flush_use_result(MYSQL *mysql);
my_bool mysql_autenticate(MYSQL *mysql, const char *passwd);
void free_old_query(MYSQL *mysql);
void end_server(MYSQL *mysql);
@@ -38,6 +39,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode,
const char *sqlstate);
+void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate);
#ifdef __cplusplus
}
#endif
diff --git a/innobase/Makefile.am b/innobase/Makefile.am
index 17d7130f3e0..8ff90d16a2c 100644
--- a/innobase/Makefile.am
+++ b/innobase/Makefile.am
@@ -22,7 +22,7 @@ TAR = gtar
noinst_HEADERS = ib_config.h
-SUBDIRS = os ut btr buf com data dict dyn eval fil fsp fut \
+SUBDIRS = os ut btr buf data dict dyn eval fil fsp fut \
ha ibuf include lock log mach mem mtr page \
pars que read rem row srv sync thr trx usr
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index eb18fecb368..77bb4231404 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -5,7 +5,7 @@ The B-tree
Created 6/2/1994 Heikki Tuuri
*******************************************************/
-
+
#include "btr0btr.h"
#ifdef UNIV_NONINL
@@ -76,9 +76,6 @@ make them consecutive on disk if possible. From the other file segment
we allocate pages for the non-leaf levels of the tree.
*/
-/* If this many inserts occur sequentially, it affects page split */
-#define BTR_PAGE_SEQ_INSERT_LIMIT 5
-
/******************************************************************
Creates a new index page to the tree (not the root, and also not
used in page reorganization). */
@@ -299,7 +296,9 @@ btr_page_alloc_for_ibuf(
new_page = buf_page_get(dict_tree_get_space(tree), node_addr.page,
RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(new_page, SYNC_TREE_NODE_NEW);
+#endif /* UNIV_SYNC_DEBUG */
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
@@ -357,7 +356,9 @@ btr_page_alloc(
new_page = buf_page_get(dict_tree_get_space(tree), new_page_no,
RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(new_page, SYNC_TREE_NODE_NEW);
+#endif /* UNIV_SYNC_DEBUG */
return(new_page);
}
@@ -398,7 +399,7 @@ btr_get_size(
n += fseg_n_reserved_pages(seg_header, &dummy, &mtr);
} else {
- ut_a(0);
+ ut_error;
}
mtr_commit(&mtr);
@@ -664,8 +665,9 @@ btr_create(
ibuf_hdr_frame = fseg_create(space, 0,
IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(ibuf_hdr_frame, SYNC_TREE_NODE_NEW);
-
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(buf_frame_get_page_no(ibuf_hdr_frame)
== IBUF_HEADER_PAGE_NO);
/* Allocate then the next page to the segment: it will be the
@@ -690,7 +692,9 @@ btr_create(
page_no = buf_frame_get_page_no(frame);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW);
+#endif /* UNIV_SYNC_DEBUG */
if (type & DICT_IBUF) {
/* It is an insert buffer tree: initialize the free list */
@@ -705,7 +709,9 @@ btr_create(
mtr);
/* The fseg create acquires a second latch on the page,
therefore we must declare it: */
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW);
+#endif /* UNIV_SYNC_DEBUG */
}
/* Create a new index page on the the allocated segment page */
@@ -1080,18 +1086,18 @@ btr_page_get_split_rec_to_left(
page = btr_cur_get_page(cursor);
insert_point = btr_cur_get_rec(cursor);
- if ((page_header_get_ptr(page, PAGE_LAST_INSERT)
- == page_rec_get_next(insert_point))
- && (page_header_get_field(page, PAGE_DIRECTION) == PAGE_LEFT)
- && ((page_header_get_field(page, PAGE_N_DIRECTION)
- >= BTR_PAGE_SEQ_INSERT_LIMIT)
- || (page_header_get_field(page, PAGE_N_DIRECTION) + 1
- >= page_get_n_recs(page)))) {
+ if (page_header_get_ptr(page, PAGE_LAST_INSERT)
+ == page_rec_get_next(insert_point)) {
infimum = page_get_infimum_rec(page);
-
- if ((infimum != insert_point)
- && (page_rec_get_next(infimum) != insert_point)) {
+
+ /* If the convergence is in the middle of a page, include also
+ the record immediately before the new insert to the upper
+ page. Otherwise, we could repeatedly move from page to page
+ lots of records smaller than the convergence point. */
+
+ if (infimum != insert_point
+ && page_rec_get_next(infimum) != insert_point) {
*split_rec = insert_point;
} else {
@@ -1125,29 +1131,29 @@ btr_page_get_split_rec_to_right(
page = btr_cur_get_page(cursor);
insert_point = btr_cur_get_rec(cursor);
- if ((page_header_get_ptr(page, PAGE_LAST_INSERT) == insert_point)
- && (page_header_get_field(page, PAGE_DIRECTION) == PAGE_RIGHT)
- && ((page_header_get_field(page, PAGE_N_DIRECTION)
- >= BTR_PAGE_SEQ_INSERT_LIMIT)
- || (page_header_get_field(page, PAGE_N_DIRECTION) + 1
- >= page_get_n_recs(page)))) {
+ /* We use eager heuristics: if the new insert would be right after
+ the previous insert on the same page, we assume that there is a
+ pattern of sequential inserts here. */
+
+ if (page_header_get_ptr(page, PAGE_LAST_INSERT) == insert_point) {
supremum = page_get_supremum_rec(page);
- if ((page_rec_get_next(insert_point) != supremum)
- && (page_rec_get_next(page_rec_get_next(insert_point))
- != supremum)
- && (page_rec_get_next(page_rec_get_next(
- page_rec_get_next(insert_point)))
- != supremum)) {
-
- /* If there are >= 3 user records up from the insert
- point, split all but 2 off */
-
- *split_rec = page_rec_get_next(page_rec_get_next(
- page_rec_get_next(insert_point)));
+ if (page_rec_get_next(insert_point) != supremum
+ && page_rec_get_next(page_rec_get_next(insert_point))
+ != supremum) {
+
+ /* If there are >= 2 user records up from the insert
+ point, split all but 1 off. We want to keep one because
+ then sequential inserts can use the adaptive hash
+ index, as they can do the necessary checks of the right
+ search position just by looking at the records on this
+ page. */
+
+ *split_rec = page_rec_get_next(
+ page_rec_get_next(insert_point));
} else {
- /* Else split at inserted record */
+ /* Else split at the new record to insert */
*split_rec = NULL;
}
@@ -1520,7 +1526,9 @@ func_start:
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(dict_tree_get_lock(tree), RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
page = btr_cur_get_page(cursor);
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 4e11407ba54..fdc8343e190 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -66,6 +66,16 @@ this many index pages */
#define BTR_BLOB_HDR_SIZE 8
/***********************************************************************
+Marks all extern fields in a record as owned by the record. This function
+should be called if the delete mark of a record is removed: a not delete
+marked record always owns all its extern fields. */
+static
+void
+btr_cur_unmark_extern_fields(
+/*=========================*/
+ rec_t* rec, /* in: record in a clustered index */
+ mtr_t* mtr); /* in: mtr */
+/***********************************************************************
Adds path information to the cursor for the current page, for which
the binary search has been performed. */
static
@@ -2672,10 +2682,11 @@ btr_estimate_number_of_different_key_vals(
btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
- /* Count the number of different key values minus one
- for each prefix of the key on this index page: we subtract
- one because otherwise our algorithm would give a wrong
- estimate for an index where there is just one key value */
+ /* Count the number of different key values for each prefix of
+ the key on this index page. If the prefix does not determine
+ the index record uniquely in te B-tree, then we subtract one
+ because otherwise our algorithm would give a wrong estimate
+ for an index where there is just one key value. */
page = btr_cur_get_page(&cursor);
@@ -2697,6 +2708,9 @@ btr_estimate_number_of_different_key_vals(
&matched_bytes);
for (j = matched_fields + 1; j <= n_cols; j++) {
+ /* We add one if this index record has
+ a different prefix from the previous */
+
n_diff[j]++;
}
@@ -2706,6 +2720,18 @@ btr_estimate_number_of_different_key_vals(
rec = page_rec_get_next(rec);
}
+ if (n_cols == dict_index_get_n_unique_in_tree(index)) {
+ /* We add one because we know that the first record
+ on the page certainly had a different prefix than the
+ last record on the previous index page in the
+ alphabetical order. Before this fix, if there was
+ just one big record on each clustered index page, the
+ algorithm grossly underestimated the number of rows
+ in the table. */
+
+ n_diff[n_cols]++;
+ }
+
total_external_size +=
btr_rec_get_externally_stored_len(rec);
mtr_commit(&mtr);
@@ -2933,7 +2959,7 @@ btr_cur_mark_dtuple_inherited_extern(
Marks all extern fields in a record as owned by the record. This function
should be called if the delete mark of a record is removed: a not delete
marked record always owns all its extern fields. */
-
+static
void
btr_cur_unmark_extern_fields(
/*=========================*/
@@ -3157,8 +3183,10 @@ btr_store_big_rec_extern_fields(
prev_page_no,
RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(prev_page,
SYNC_EXTERN_STORAGE);
+#endif /* UNIV_SYNC_DEBUG */
mlog_write_ulint(prev_page + FIL_PAGE_DATA
+ BTR_BLOB_HDR_NEXT_PAGE_NO,
@@ -3193,9 +3221,9 @@ btr_store_big_rec_extern_fields(
rec_page = buf_page_get(space_id,
buf_frame_get_page_no(data),
RW_X_LATCH, &mtr);
-
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(rec_page, SYNC_NO_ORDER_CHECK);
-
+#endif /* UNIV_SYNC_DEBUG */
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, 0,
MLOG_4BYTES, &mtr);
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN + 4,
@@ -3287,9 +3315,9 @@ btr_free_externally_stored_field(
rec_page = buf_page_get(buf_frame_get_space_id(data),
buf_frame_get_page_no(data), RW_X_LATCH, &mtr);
-
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(rec_page, SYNC_NO_ORDER_CHECK);
-
+#endif /* UNIV_SYNC_DEBUG */
space_id = mach_read_from_4(data + local_len
+ BTR_EXTERN_SPACE_ID);
@@ -3332,9 +3360,9 @@ btr_free_externally_stored_field(
}
page = buf_page_get(space_id, page_no, RW_X_LATCH, &mtr);
-
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_EXTERN_STORAGE);
-
+#endif /* UNIV_SYNC_DEBUG */
next_page_no = mach_read_from_4(page + FIL_PAGE_DATA
+ BTR_BLOB_HDR_NEXT_PAGE_NO);
@@ -3512,9 +3540,9 @@ btr_copy_externally_stored_field(
mtr_start(&mtr);
page = buf_page_get(space_id, page_no, RW_S_LATCH, &mtr);
-
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_EXTERN_STORAGE);
-
+#endif /* UNIV_SYNC_DEBUG */
blob_header = page + offset;
part_len = btr_blob_get_part_len(blob_header);
diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c
index 39e70d91be8..cf8a612ef28 100644
--- a/innobase/btr/btr0pcur.c
+++ b/innobase/btr/btr0pcur.c
@@ -238,9 +238,9 @@ btr_pcur_restore_position(
cursor->block_when_stored, page,
cursor->modify_clock, mtr)) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
-
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
-
+#endif /* UNIV_SYNC_DEBUG */
if (cursor->rel_pos == BTR_PCUR_ON) {
cursor->latch_mode = latch_mode;
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c
index 8a59be12a32..2093d5ea757 100644
--- a/innobase/btr/btr0sea.c
+++ b/innobase/btr/btr0sea.c
@@ -22,7 +22,9 @@ Created 2/17/1996 Heikki Tuuri
ulint btr_search_this_is_zero = 0; /* A dummy variable to fool the
compiler */
+#ifdef UNIV_SEARCH_PERF_STAT
ulint btr_search_n_succ = 0;
+#endif /* UNIV_SEARCH_PERF_STAT */
ulint btr_search_n_hash_fail = 0;
byte btr_sea_pad1[64]; /* padding to prevent other memory update
@@ -93,8 +95,10 @@ btr_search_check_free_space_in_heap(void)
hash_table_t* table;
mem_heap_t* heap;
- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)
- && !rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
table = btr_search_sys->hash_index;
@@ -194,8 +198,10 @@ btr_search_info_update_hash(
ulint n_unique;
int cmp;
- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)
- && !rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
index = cursor->index;
@@ -317,10 +323,12 @@ btr_search_update_block_hash_info(
buf_block_t* block, /* in: buffer block */
btr_cur_t* cursor) /* in: cursor */
{
- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)
- && !rw_lock_own(&btr_search_latch, RW_LOCK_EX));
- ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
- || rw_lock_own(&(block->lock), RW_LOCK_EX));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+ ut_ad(rw_lock_own(&((buf_block_t*) block)->lock, RW_LOCK_SHARED)
+ || rw_lock_own(&((buf_block_t*) block)->lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(cursor);
info->last_hash_succ = FALSE;
@@ -398,9 +406,11 @@ btr_search_update_hash_ref(
dulint tree_id;
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
if (block->is_hashed
&& (info->n_hash_potential > 0)
&& (block->curr_n_fields == info->n_fields)
@@ -419,7 +429,9 @@ btr_search_update_hash_ref(
fold = rec_fold(rec, block->curr_n_fields,
block->curr_n_bytes, tree_id);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ha_insert_for_fold(btr_search_sys->hash_index, fold, rec);
}
@@ -439,8 +451,10 @@ btr_search_info_update_slow(
ulint* params;
ulint* params2;
- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)
- && !rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
block = buf_block_align(btr_cur_get_rec(cursor));
@@ -762,7 +776,9 @@ btr_search_guess_on_hash(
can_only_compare_to_cursor_rec = FALSE;
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH);
+#endif /* UNIV_SYNC_DEBUG */
}
block = buf_block_align(page);
@@ -910,10 +926,12 @@ btr_search_drop_page_hash_index(
ulint n_recs;
ulint* folds;
ulint i;
-
- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)
- && !rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
rw_lock_s_lock(&btr_search_latch);
block = buf_block_align(page);
@@ -927,9 +945,11 @@ btr_search_drop_page_hash_index(
table = btr_search_sys->hash_index;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|| rw_lock_own(&(block->lock), RW_LOCK_EX)
|| (block->buf_fix_count == 0));
+#endif /* UNIV_SYNC_DEBUG */
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
@@ -1031,8 +1051,10 @@ btr_search_drop_page_hash_when_freed(
BUF_GET_IF_IN_POOL, IB__FILE__, __LINE__,
&mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH);
-
+#endif /* UNIV_SYNC_DEBUG */
+
btr_search_drop_page_hash_index(page);
mtr_commit(&mtr);
@@ -1072,9 +1094,11 @@ btr_search_build_page_hash_index(
block = buf_block_align(page);
table = btr_search_sys->hash_index;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
rw_lock_s_lock(&btr_search_latch);
@@ -1237,8 +1261,10 @@ btr_search_move_or_delete_hash_entries(
block = buf_block_align(page);
new_block = buf_block_align(new_page);
- ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)
- && rw_lock_own(&(new_block->lock), RW_LOCK_EX));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
+ ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
rw_lock_s_lock(&btr_search_latch);
@@ -1298,7 +1324,9 @@ btr_search_update_hash_on_delete(
block = buf_block_align(rec);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
if (!block->is_hashed) {
@@ -1339,7 +1367,9 @@ btr_search_update_hash_node_on_insert(
block = buf_block_align(rec);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
if (!block->is_hashed) {
@@ -1400,7 +1430,9 @@ btr_search_update_hash_on_insert(
block = buf_block_align(rec);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
if (!block->is_hashed) {
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 2af971d38fd..844880238fa 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -476,11 +476,11 @@ buf_block_init(
rw_lock_create(&(block->lock));
ut_ad(rw_lock_validate(&(block->lock)));
-
+
#ifdef UNIV_SYNC_DEBUG
rw_lock_create(&(block->debug_latch));
rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK);
-#endif
+#endif /* UNIV_SYNC_DEBUG */
}
/************************************************************************
@@ -1325,9 +1325,9 @@ buf_page_optimistic_get_func(
}
if (!UT_DULINT_EQ(modify_clock, block->modify_clock)) {
-
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(block->frame, SYNC_NO_ORDER_CHECK);
-
+#endif /* UNIV_SYNC_DEBUG */
if (rw_latch == RW_S_LATCH) {
rw_lock_s_unlock(&(block->lock));
} else {
@@ -1527,7 +1527,9 @@ buf_page_init(
in units of a page */
buf_block_t* block) /* in: block to init */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state != BUF_BLOCK_FILE_PAGE);
/* Set the state of the block */
diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
index cdea764971e..c568d5925fa 100644
--- a/innobase/buf/buf0flu.c
+++ b/innobase/buf/buf0flu.c
@@ -48,7 +48,9 @@ buf_flush_insert_into_flush_list(
/*=============================*/
buf_block_t* block) /* in: block which is modified */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
@@ -76,7 +78,9 @@ buf_flush_insert_sorted_into_flush_list(
buf_block_t* prev_b;
buf_block_t* b;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
prev_b = NULL;
b = UT_LIST_GET_FIRST(buf_pool->flush_list);
@@ -108,7 +112,9 @@ buf_flush_ready_for_replace(
buf_block_t* block) /* in: buffer control block, must be in state
BUF_BLOCK_FILE_PAGE and in the LRU list */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
@@ -132,7 +138,9 @@ buf_flush_ready_for_flush(
BUF_BLOCK_FILE_PAGE */
ulint flush_type)/* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
@@ -163,8 +171,9 @@ buf_flush_write_complete(
buf_block_t* block) /* in: pointer to the block in question */
{
ut_ad(block);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
block->oldest_modification = ut_dulint_zero;
@@ -248,7 +257,7 @@ buf_flush_buffered_writes(void)
"InnoDB: files.\n",
(ulong) block->offset, (ulong) block->space);
- ut_a(0);
+ ut_error;
}
}
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index db876c416cc..c5faec17890 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -310,11 +310,15 @@ loop:
fprintf(stderr,
" InnoDB: ERROR: over 9 / 10 of the buffer pool is occupied by\n"
-"InnoDB: lock heaps or the adaptive hash index!\n"
+"InnoDB: lock heaps or the adaptive hash index! Check that your\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: We intentionally generate a seg fault to print a stack trace\n"
-"InnoDB: on Linux!\n");
+"InnoDB: on Linux!\n",
+ (ulong)(buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE)));
- ut_a(0);
+ ut_error;
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) {
@@ -471,7 +475,9 @@ buf_LRU_old_adjust_len(void)
ulint new_len;
ut_a(buf_pool->LRU_old);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(3 * (BUF_LRU_OLD_MIN_LEN / 8) > BUF_LRU_OLD_TOLERANCE + 5);
for (;;) {
@@ -544,7 +550,9 @@ buf_LRU_remove_block(
{
ut_ad(buf_pool);
ut_ad(block);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(block->in_LRU_list);
@@ -608,7 +616,9 @@ buf_LRU_add_block_to_end_low(
ut_ad(buf_pool);
ut_ad(block);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
@@ -671,7 +681,9 @@ buf_LRU_add_block_low(
ut_ad(buf_pool);
ut_ad(block);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(!block->in_LRU_list);
@@ -772,7 +784,9 @@ buf_LRU_block_free_non_file_page(
/*=============================*/
buf_block_t* block) /* in: block, must not contain a file page */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(block);
ut_a((block->state == BUF_BLOCK_MEMORY)
@@ -809,7 +823,9 @@ buf_LRU_block_remove_hashed_page(
be in a state where it can be freed; there
may or may not be a hash index to the page */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(block);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
@@ -863,7 +879,9 @@ buf_LRU_block_free_hashed_page(
buf_block_t* block) /* in: block, must contain a file page and
be in a state where it can be freed */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_REMOVE_HASH);
block->state = BUF_BLOCK_MEMORY;
diff --git a/innobase/com/Makefile.am b/innobase/com/Makefile.am
deleted file mode 100644
index a3d2f8a76c6..00000000000
--- a/innobase/com/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-# & Innobase Oy
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-include ../include/Makefile.i
-
-noinst_LIBRARIES = libcom.a
-
-libcom_a_SOURCES = com0com.c com0shm.c
-
-EXTRA_PROGRAMS =
diff --git a/innobase/com/com0com.c b/innobase/com/com0com.c
deleted file mode 100644
index 94585d9f269..00000000000
--- a/innobase/com/com0com.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/******************************************************
-The communication primitives
-
-(c) 1995 Innobase Oy
-
-Created 9/23/1995 Heikki Tuuri
-*******************************************************/
-
-#include "com0com.h"
-#ifdef UNIV_NONINL
-#include "com0com.ic"
-#endif
-
-#include "mem0mem.h"
-#include "com0shm.h"
-
-/*
- IMPLEMENTATION OF COMMUNICATION PRIMITIVES
- ==========================================
-
-The primitives provide a uniform function interface for
-use in communication. The primitives have been modeled
-after the Windows Sockets interface. Below this uniform
-API, the precise methods of communication, for example,
-shared memory or Berkeley sockets, can be implemented
-as subroutines.
-*/
-
-struct com_endpoint_struct{
- ulint type; /* endpoint type */
- void* par; /* type-specific data structures */
- ibool bound; /* TRUE if the endpoint has been
- bound to an address */
-};
-
-/*************************************************************************
-Accessor functions for an endpoint */
-UNIV_INLINE
-ulint
-com_endpoint_get_type(
-/*==================*/
- com_endpoint_t* ep)
-{
- ut_ad(ep);
- return(ep->type);
-}
-
-UNIV_INLINE
-void
-com_endpoint_set_type(
-/*==================*/
- com_endpoint_t* ep,
- ulint type)
-{
- ut_ad(ep);
- ut_ad(type == COM_SHM);
-
- ep->type = type;
-}
-
-UNIV_INLINE
-void*
-com_endpoint_get_par(
-/*=================*/
- com_endpoint_t* ep)
-{
- ut_ad(ep);
- return(ep->par);
-}
-
-UNIV_INLINE
-void
-com_endpoint_set_par(
-/*=================*/
- com_endpoint_t* ep,
- void* par)
-{
- ut_ad(ep);
- ut_ad(par);
-
- ep->par = par;
-}
-
-UNIV_INLINE
-ibool
-com_endpoint_get_bound(
-/*===================*/
- com_endpoint_t* ep)
-{
- ut_ad(ep);
- return(ep->bound);
-}
-
-UNIV_INLINE
-void
-com_endpoint_set_bound(
-/*===================*/
- com_endpoint_t* ep,
- ibool bound)
-{
- ut_ad(ep);
-
- ep->bound = bound;
-}
-
-
-/*************************************************************************
-Creates a communications endpoint. */
-
-com_endpoint_t*
-com_endpoint_create(
-/*================*/
- /* out, own: communications endpoint, NULL if
- did not succeed */
- ulint type) /* in: communication type of endpoint:
- only COM_SHM supported */
-{
- com_endpoint_t* ep;
- void* par;
-
- ep = mem_alloc(sizeof(com_endpoint_t));
-
- com_endpoint_set_type(ep, type);
- com_endpoint_set_bound(ep, FALSE);
-
- if (type == COM_SHM) {
- par = com_shm_endpoint_create();
- com_endpoint_set_par(ep, par);
- } else {
- par = NULL;
- ut_error;
- }
-
- if (par != NULL) {
- return(ep);
- } else {
- mem_free(ep);
- return(NULL);
- }
-}
-
-/*************************************************************************
-Frees a communications endpoint. */
-
-ulint
-com_endpoint_free(
-/*==============*/
- /* out: O if succeed, else error number */
- com_endpoint_t* ep) /* in, own: communications endpoint */
-{
- ulint type;
- ulint ret;
- void* par;
-
- type = com_endpoint_get_type(ep);
- par = com_endpoint_get_par(ep);
-
- if (type == COM_SHM) {
- ret = com_shm_endpoint_free((com_shm_endpoint_t*)par);
- } else {
- ret = 0;
- ut_error;
- }
-
- if (ret) {
- return(ret);
- } else {
- mem_free(ep);
- return(0);
- }
-}
-
-/*************************************************************************
-Sets an option, like the maximum datagram size for an endpoint.
-The options may vary depending on the endpoint type. */
-
-ulint
-com_endpoint_set_option(
-/*====================*/
- /* out: 0 if succeed, else error number */
- com_endpoint_t* ep, /* in: endpoint */
- ulint optno, /* in: option number, only
- COM_OPT_MAX_DGRAM_SIZE currently supported */
- byte* optval, /* in: pointer to a buffer containing the
- option value to set */
- ulint optlen) /* in: option value buffer length */
-{
- ulint type;
- ulint ret;
- void* par;
-
- type = com_endpoint_get_type(ep);
- par = com_endpoint_get_par(ep);
-
- if (type == COM_SHM) {
- ret = com_shm_endpoint_set_option((com_shm_endpoint_t*)par,
- optno, optval, optlen);
- } else {
- ret = 0;
- ut_error;
- }
-
- return(ret);
-}
-
-/*************************************************************************
-Binds a communications endpoint to the specified address. */
-
-ulint
-com_bind(
-/*=====*/
- /* out: 0 if succeed, else error number */
- com_endpoint_t* ep, /* in: communications endpoint */
- char* name, /* in: address name */
- ulint len) /* in: name length */
-{
- ulint type;
- ulint ret;
- void* par;
-
- ut_ad(len <= COM_MAX_ADDR_LEN);
-
- if (com_endpoint_get_bound(ep)) {
- return(COM_ERR_ALREADY_BOUND);
- }
-
- type = com_endpoint_get_type(ep);
- par = com_endpoint_get_par(ep);
-
- if (type == COM_SHM) {
- ret = com_shm_bind((com_shm_endpoint_t*)par, name, len);
- } else {
- ret = 0;
- ut_error;
- }
-
- if (ret == 0) {
- com_endpoint_set_bound(ep, TRUE);
- }
-
- return(ret);
-}
-
-/*************************************************************************
-Waits for a datagram to arrive at an endpoint. */
-
-ulint
-com_recvfrom(
-/*=========*/
- /* out: 0 if succeed, else error number */
- com_endpoint_t* ep, /* in: communications endpoint */
- byte* buf, /* out: datagram buffer; the buffer is
- supplied by the caller */
- ulint buf_len,/* in: datagram buffer length */
- ulint* len, /* out: datagram length */
- char* from, /* out: address name buffer; the buffer is
- supplied by the caller */
- ulint from_len,/* in: address name buffer length */
- ulint* addr_len)/* out: address name length */
-{
- ulint type;
- ulint ret;
- void* par;
-
- if (!com_endpoint_get_bound(ep)) {
-
- return(COM_ERR_NOT_BOUND);
- }
-
- type = com_endpoint_get_type(ep);
- par = com_endpoint_get_par(ep);
-
- if (type == COM_SHM) {
- ret = com_shm_recvfrom((com_shm_endpoint_t*)par,
- buf, buf_len, len, from, from_len,
- addr_len);
- } else {
- ret = 0;
-
- ut_error;
- }
-
- return(ret);
-}
-
-/*************************************************************************
-Sends a datagram to the specified destination. */
-
-ulint
-com_sendto(
-/*=======*/
- /* out: 0 if succeed, else error number */
- com_endpoint_t* ep, /* in: communications endpoint */
- byte* buf, /* in: datagram buffer */
- ulint len, /* in: datagram length */
- char* to, /* in: address name buffer */
- ulint tolen) /* in: address name length */
-{
- ulint type;
- ulint ret;
- void* par;
-
- if (!com_endpoint_get_bound(ep)) {
- return(COM_ERR_NOT_BOUND);
- }
-
- type = com_endpoint_get_type(ep);
- par = com_endpoint_get_par(ep);
-
- if (type == COM_SHM) {
- ret = com_shm_sendto((com_shm_endpoint_t*)par, buf, len,
- to, tolen);
- } else {
- ret = 0;
- ut_error;
- }
-
- return(ret);
-}
-
-/*************************************************************************
-Gets the maximum datagram size for an endpoint. */
-
-ulint
-com_endpoint_get_max_size(
-/*======================*/
- /* out: maximum size */
- com_endpoint_t* ep) /* in: endpoint */
-{
- ulint type;
- ulint ret;
- void* par;
-
- type = com_endpoint_get_type(ep);
- par = com_endpoint_get_par(ep);
-
- if (type == COM_SHM) {
- ret = com_shm_endpoint_get_size((com_shm_endpoint_t*)par);
- } else {
- ret = 0;
- ut_error;
- }
-
- return(ret);
-}
diff --git a/innobase/com/com0shm.c b/innobase/com/com0shm.c
deleted file mode 100644
index 09876e6e8b5..00000000000
--- a/innobase/com/com0shm.c
+++ /dev/null
@@ -1,1130 +0,0 @@
-/******************************************************
-The communication through shared memory
-
-(c) 1995 Innobase Oy
-
-Created 9/25/1995 Heikki Tuuri
-*******************************************************/
-
-#include "com0shm.h"
-#ifdef UNIV_NONINL
-#include "com0shm.ic"
-#endif
-
-#include "mem0mem.h"
-#include "ut0mem.h"
-#include "com0com.h"
-#include "os0shm.h"
-#include "sync0sync.h"
-#include "sync0ipm.h"
-#include "hash0hash.h"
-
-/*
- IMPLEMENTATION OF COMMUNICATION PRIMITIVES
- ==========================================
-
-When bind is called for an endpoint, a shared memory area of
-a size specified by com_shm_set_option is created with the
-name of the address given concatenated to "_IBSHM".
-Also a mutex is created for controlling the access to the
-shared memory area. The name of the mutex is address + "_IBSHM_MTX".
-An event with name address + "_IBSHM_EV_NE" is created. This event
-is in signaled state when the shared memory area is not empty, i.e.,
-there is a datagram to read. An event address + "_IBSHM_EV_EM"
-is signaled, when the area is empty, i.e., a datagram can be
-written to it.
-
-The shared memory area consists of an info struct
-at the beginning, containing fields telling:
-if the area is valid, i.e., is anybody going to
-read it, whether it currently contains a datagram, the
-length of the address from which the datagram was received,
-the length of the datagram, and the maximum allowed length of
-a datagram.
-After the info struct, there is a string of bytes
-containing the sender address and the data
-of the datagram.
-*/
-
-/* The following is set TRUE when the first endpoint is created. */
-
-ibool com_shm_initialized = FALSE;
-
-/* When a datagram is sent, the shared memory area
-corresponding to the destination address is mapped
-to the address space of this (sender) process.
-We preserve it and keep the relevant info in the
-following list. We can save a lot of CPU time
-if the destination can be found on the list. The list is
-protected by the mutex below. */
-
-mutex_t com_shm_destination_mutex;
-hash_table_t* com_shm_destination_cache;
-UT_LIST_BASE_NODE_T(com_shm_endpoint_t)
- com_shm_destination_list;
-
-/* The number of successfully bound endpoints in this process. When this
-number drops to 0, the destination cache is freed. This variable is protected
-by com_shm_destination_mutex above. */
-
-ulint com_shm_bind_count = 0;
-
-/* The performance of communication in NT depends on how
-many times a system call is made (excluding os_thread_yield,
-as that is the fastest way to switch thread).
-The following variable counts such events. */
-
-ulint com_shm_system_call_count = 0;
-
-/* The info struct at the beginning of a shared memory area */
-
-typedef struct com_shm_info_struct com_shm_info_t;
-
-/* An area of shared memory consists of an info struct followed
-by a string of bytes. */
-
-typedef com_shm_info_t com_shm_t;
-
-struct com_shm_endpoint_struct{
- ibool owns_shm; /* This is true if the shared memory
- area is owned by this endpoint structure
- (it may also be opened for this endpoint,
- not created, in which case does not own it) */
- char* addr; /* pointer to address the endpoint is bound
- to, NULL if not bound */
- ulint addr_len; /* address length */
- ulint size; /* maximum allowed datagram size, initialized
- to 0 at creation */
- os_shm_t shm; /* operating system handle of the shared
- memory area */
- com_shm_t* map; /* pointer to the start address of the shared
- memory area */
- os_event_t not_empty; /* this is in the signaled state if
- the area currently may contain a datagram;
- NOTE: automatic event */
- os_event_t empty; /* this is in the signaled state if the area
- currently may be empty; NOTE: automatic
- event */
- ip_mutex_hdl_t* ip_mutex; /* handle to the interprocess mutex
- protecting the shared memory */
- UT_LIST_NODE_T(com_shm_endpoint_t) list; /* If the endpoint struct
- is inserted into a list, this contains
- pointers to next and prev */
- com_shm_endpoint_t* addr_hash;
- /* hash table link */
-};
-
-struct com_shm_info_struct{
- ulint valid; /* This is COM_SHM_VALID if the creator
- of the shared memory area has it still
- mapped to its address space. Otherwise,
- we may conclude that the datagram cannot
- be delivered. */
- ibool not_empty; /* TRUE if the area currently contains
- a datagram */
- ulint empty_waiters; /* Count of (writer) threads which are
- waiting for the empty-event */
- ulint max_len;/* maximum allowed length for a datagram */
- ulint addr_len;/* address length for the sender address */
- ulint data_len;/* datagram length */
- ip_mutex_t ip_mutex;/* fast interprocess mutex protecting
- the shared memory area */
-};
-
-#define COM_SHM_VALID 76640
-
-/*************************************************************************
-Accessor functions for a shared memory endpoint */
-
-UNIV_INLINE
-ibool
-com_shm_endpoint_get_owns_shm(
-/*==========================*/
- com_shm_endpoint_t* ep)
-{
- ut_ad(ep);
- return(ep->owns_shm);
-}
-
-UNIV_INLINE
-void
-com_shm_endpoint_set_owns_shm(
-/*==========================*/
- com_shm_endpoint_t* ep,
- ibool flag)
-{
- ut_ad(ep);
-
- ep->owns_shm = flag;
-}
-
-UNIV_INLINE
-char*
-com_shm_endpoint_get_addr(
-/*======================*/
- com_shm_endpoint_t* ep)
-{
- ut_ad(ep);
- return(ep->addr);
-}
-
-UNIV_INLINE
-void
-com_shm_endpoint_set_addr(
-/*======================*/
- com_shm_endpoint_t* ep,
- char* addr)
-{
- ut_ad(ep);
-
- ep->addr = addr;
-}
-
-UNIV_INLINE
-ulint
-com_shm_endpoint_get_addr_len(
-/*==========================*/
- com_shm_endpoint_t* ep)
-{
- return(ep->addr_len);
-}
-
-UNIV_INLINE
-void
-com_shm_endpoint_set_addr_len(
-/*==========================*/
- com_shm_endpoint_t* ep,
- ulint len)
-{
- ut_ad(ep);
- ut_ad(len > 0);
-
- ep->addr_len = len;
-}
-
-ulint
-com_shm_endpoint_get_size(
-/*======================*/
- com_shm_endpoint_t* ep)
-{
- return(ep->size);
-}
-
-UNIV_INLINE
-void
-com_shm_endpoint_set_size(
-/*======================*/
- com_shm_endpoint_t* ep,
- ulint size)
-{
- ut_ad(ep);
-
- ep->size = size;
-}
-
-UNIV_INLINE
-os_shm_t
-com_shm_endpoint_get_shm(
-/*=====================*/
- com_shm_endpoint_t* ep)
-{
- return(ep->shm);
-}
-
-UNIV_INLINE
-void
-com_shm_endpoint_set_shm(
-/*=====================*/
- com_shm_endpoint_t* ep,
- os_shm_t shm)
-{
- ut_ad(ep);
- ut_ad(shm);
-
- ep->shm = shm;
-}
-
-UNIV_INLINE
-com_shm_t*
-com_shm_endpoint_get_map(
-/*=====================*/
- com_shm_endpoint_t* ep)
-{
- return(ep->map);
-}
-
-UNIV_INLINE
-void
-com_shm_endpoint_set_map(
-/*=====================*/
- com_shm_endpoint_t* ep,
- com_shm_t* map)
-{
- ut_ad(ep);
- ut_ad(map);
-
- ep->map = map;
-}
-
-UNIV_INLINE
-os_event_t
-com_shm_endpoint_get_empty(
-/*=======================*/
- com_shm_endpoint_t* ep)
-{
- return(ep->empty);
-}
-
-UNIV_INLINE
-void
-com_shm_endpoint_set_empty(
-/*=======================*/
- com_shm_endpoint_t* ep,
- os_event_t event)
-{
- ut_ad(ep);
- ut_ad(event);
-
- ep->empty = event;
-}
-
-UNIV_INLINE
-os_event_t
-com_shm_endpoint_get_not_empty(
-/*===========================*/
- com_shm_endpoint_t* ep)
-{
- return(ep->not_empty);
-}
-
-UNIV_INLINE
-void
-com_shm_endpoint_set_not_empty(
-/*===========================*/
- com_shm_endpoint_t* ep,
- os_event_t event)
-{
- ut_ad(ep);
- ut_ad(event);
-
- ep->not_empty = event;
-}
-
-/************************************************************************
-Accessor functions for the shared memory area info struct. */
-UNIV_INLINE
-ulint
-com_shm_get_valid(
-/*==============*/
- com_shm_info_t* info)
-{
- return(info->valid);
-}
-
-UNIV_INLINE
-void
-com_shm_set_valid(
-/*==============*/
- com_shm_info_t* info,
- ulint flag)
-{
- ut_ad(info);
-
- info->valid = flag;
-}
-
-UNIV_INLINE
-ibool
-com_shm_get_not_empty(
-/*==================*/
- com_shm_info_t* info)
-{
- return(info->not_empty);
-}
-
-UNIV_INLINE
-void
-com_shm_set_not_empty(
-/*==================*/
- com_shm_info_t* info,
- ibool flag)
-{
- ut_ad(info);
-
- info->not_empty = flag;
-}
-
-UNIV_INLINE
-ulint
-com_shm_get_empty_waiters(
-/*======================*/
- com_shm_info_t* info)
-{
- ut_ad(info->empty_waiters < 1000);
-
- return(info->empty_waiters);
-}
-
-UNIV_INLINE
-void
-com_shm_set_empty_waiters(
-/*======================*/
- com_shm_info_t* info,
- ulint count)
-{
- ut_ad(info);
- ut_ad(count < 1000);
-
- info->empty_waiters = count;
-}
-
-UNIV_INLINE
-ulint
-com_shm_get_max_len(
-/*================*/
- com_shm_info_t* info)
-{
- return(info->max_len);
-}
-
-UNIV_INLINE
-void
-com_shm_set_max_len(
-/*================*/
- com_shm_info_t* info,
- ulint len)
-{
- ut_ad(info);
- ut_ad(len > 0);
-
- info->max_len = len;
-}
-
-UNIV_INLINE
-ulint
-com_shm_get_addr_len(
-/*=================*/
- com_shm_info_t* info)
-{
- return(info->addr_len);
-}
-
-UNIV_INLINE
-void
-com_shm_set_addr_len(
-/*=================*/
- com_shm_info_t* info,
- ulint len)
-{
- ut_ad(info);
- ut_ad(len > 0);
-
- info->addr_len = len;
-}
-
-UNIV_INLINE
-ulint
-com_shm_get_data_len(
-/*=================*/
- com_shm_info_t* info)
-{
- return(info->data_len);
-}
-
-UNIV_INLINE
-void
-com_shm_set_data_len(
-/*=================*/
- com_shm_info_t* info,
- ulint len)
-{
- ut_ad(info);
- ut_ad(len > 0);
-
- info->data_len = len;
-}
-
-UNIV_INLINE
-ip_mutex_t*
-com_shm_get_ip_mutex(
-/*=================*/
- com_shm_info_t* info)
-{
- return(&(info->ip_mutex));
-}
-
-/*************************************************************************
-Accessor functions for the address and datagram fields inside a
-shared memory area. */
-
-UNIV_INLINE
-char*
-com_shm_get_addr(
-/*=============*/
- com_shm_t* area)
-{
- return((char*)area + sizeof(com_shm_info_t));
-}
-
-UNIV_INLINE
-byte*
-com_shm_get_data(
-/*=============*/
- com_shm_t* area)
-{
- return((byte*)com_shm_get_addr(area) + com_shm_get_addr_len(area));
-}
-
-/*************************************************************************
-Initializes the shared memory communication system for this
-process. */
-UNIV_INLINE
-void
-com_shm_init(void)
-/*==============*/
-{
- mutex_create(&com_shm_destination_mutex);
-
- mutex_set_level(&com_shm_destination_mutex, SYNC_ANY_LATCH);
-
- com_shm_destination_cache = hash_create(1000);
-
- UT_LIST_INIT(com_shm_destination_list);
-
- com_shm_initialized = TRUE;
-}
-
-/*************************************************************************
-Reserves the ip mutex of the shared memory area of an endpoint. */
-UNIV_INLINE
-void
-com_shm_enter(
-/*==========*/
- com_shm_endpoint_t* ep)
-{
- ulint ret;
-
- ret = ip_mutex_enter(ep->ip_mutex, 10000000);
-
- if (ret != 0) {
- mutex_list_print_info();
-
- ut_error;
- }
-}
-
-/*************************************************************************
-Releases the ip mutex of the shared memory area of an endpoint. */
-UNIV_INLINE
-void
-com_shm_exit(
-/*=========*/
- com_shm_endpoint_t* ep)
-{
- ip_mutex_exit(ep->ip_mutex);
-}
-
-/*************************************************************************
-Looks for the given address in the cached destination addresses. */
-UNIV_INLINE
-com_shm_endpoint_t*
-com_shm_destination_cache_search(
-/*=============================*/
- /* out: cached endpoint structure if found, else NULL */
- char* addr, /* in: destination address */
- ulint len) /* in: address length */
-{
- com_shm_endpoint_t* ep;
- ulint fold;
-
- fold = ut_fold_binary((byte*)addr, len);
-/*
- printf("Searching dest. cache %s %lu fold %lu\n", addr, len, fold);
-*/
- mutex_enter(&com_shm_destination_mutex);
-
- HASH_SEARCH(addr_hash, com_shm_destination_cache, fold, ep,
- ((ep->addr_len == len)
- && (0 == ut_memcmp(addr, ep->addr, len))));
-
- mutex_exit(&com_shm_destination_mutex);
-
- return(ep);
-}
-
-/*************************************************************************
-Inserts the given endpoint structure in the cached destination addresses. */
-static
-void
-com_shm_destination_cache_insert(
-/*=============================*/
- com_shm_endpoint_t* ep) /* in: endpoint struct to insert */
-{
- ulint fold;
-
- fold = ut_fold_binary((byte*)(ep->addr), ep->addr_len);
-
- mutex_enter(&com_shm_destination_mutex);
-
- /* Add to hash table */
- HASH_INSERT(com_shm_endpoint_t,
- addr_hash, com_shm_destination_cache, fold, ep);
-
- UT_LIST_ADD_LAST(list, com_shm_destination_list, ep);
-
-/* printf("Inserting to dest. cache %s %lu fold %lu\n", ep->addr,
- ep->addr_len, fold);
-*/
- mutex_exit(&com_shm_destination_mutex);
-}
-
-/*************************************************************************
-Frees the endpoint structs in the destination cache if the bind count is zero.
-If it is not, some send operation may just be using a cached endpoint and it
-cannot be freed. */
-static
-void
-com_shm_destination_cache_no_binds(void)
-/*====================================*/
-{
- com_shm_endpoint_t* ep;
- ulint fold;
-
- mutex_enter(&com_shm_destination_mutex);
-
- if (com_shm_bind_count != 0) {
- mutex_exit(&com_shm_destination_mutex);
-
- return;
- }
-
- while (UT_LIST_GET_LEN(com_shm_destination_list) != 0) {
-
- ep = UT_LIST_GET_FIRST(com_shm_destination_list);
-
- UT_LIST_REMOVE(list, com_shm_destination_list, ep);
-
- fold = ut_fold_binary((byte*)ep->addr, ep->addr_len);
-/*
- printf("Deleting from dest. cache %s %lu fold %lu\n",
- ep->addr,
- ep->addr_len, fold);
-*/
- HASH_DELETE(com_shm_endpoint_t, addr_hash,
- com_shm_destination_cache, fold, ep);
-
- com_shm_endpoint_free(ep);
- }
-
- mutex_exit(&com_shm_destination_mutex);
-}
-
-/***********************************************************************
-Unbinds an endpoint at the time of freeing. */
-static
-void
-com_shm_unbind(
-/*===========*/
- com_shm_endpoint_t* ep) /* in: endpoint */
-{
- com_shm_t* map;
-
- map = com_shm_endpoint_get_map(ep);
-
- /* Mark the shared memory area invalid */
-
- com_shm_set_valid(map, 0);
-
- /* Decrement the count of bindings */
-
- mutex_enter(&com_shm_destination_mutex);
-
- com_shm_bind_count--;
-
- mutex_exit(&com_shm_destination_mutex);
-
- /* If there are no binds left, free the cached endpoints */
-
- com_shm_destination_cache_no_binds();
-}
-
-/*************************************************************************
-Creates a communications endpoint. */
-
-com_shm_endpoint_t*
-com_shm_endpoint_create(void)
-/*=========================*/
- /* out, own: communications endpoint, NULL if
- did not succeed */
-{
- com_shm_endpoint_t* ep;
-
- if (!com_shm_initialized) {
-
- com_shm_init();
- }
-
- ep = mem_alloc(sizeof(com_shm_endpoint_t));
-
- com_shm_endpoint_set_owns_shm(ep, FALSE);
- com_shm_endpoint_set_addr(ep, NULL);
- com_shm_endpoint_set_size(ep, 0);
-
- return(ep);
-}
-
-/*************************************************************************
-Frees a communications endpoint. */
-
-ulint
-com_shm_endpoint_free(
-/*==================*/
- /* out: O if succeed, else error number */
- com_shm_endpoint_t* ep) /* in, own: communications endpoint */
-{
- com_shm_t* map;
-
- ut_ad(ep);
-
- if (com_shm_endpoint_get_addr(ep) != NULL) {
-
- map = com_shm_endpoint_get_map(ep);
-
- if (com_shm_endpoint_get_owns_shm(ep)) {
-
- com_shm_unbind(ep);
- }
-
- /* We do not destroy the data structures in the shared memory
- area, because we cannot be sure that there is currently no
- process accessing it. Therefore we just close the ip_mutex
- residing in the area. */
-
- ip_mutex_close(ep->ip_mutex);
-
- os_event_free(com_shm_endpoint_get_not_empty(ep));
- os_event_free(com_shm_endpoint_get_empty(ep));
-
- os_shm_unmap(map);
- os_shm_free(com_shm_endpoint_get_shm(ep));
-
- mem_free(com_shm_endpoint_get_addr(ep));
- }
-
- mem_free(ep);
-
- return(0);
-}
-
-/*************************************************************************
-Sets an option, like the maximum datagram size for an endpoint.
-The options may vary depending on the endpoint type. */
-
-ulint
-com_shm_endpoint_set_option(
-/*========================*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: endpoint */
- ulint optno, /* in: option number, only
- COM_OPT_MAX_DGRAM_SIZE currently supported */
- byte* optval, /* in: pointer to a buffer containing the
- option value to set */
- ulint optlen) /* in: option value buffer length */
-{
- ulint size;
-
- UT_NOT_USED(optlen);
-
- ut_ad(ep);
- ut_a(optno == COM_OPT_MAX_DGRAM_SIZE);
- ut_ad(NULL == com_shm_endpoint_get_addr(ep));
-
- size = *((ulint*)optval);
-
- ut_ad(size > 0);
-
- com_shm_endpoint_set_size(ep, size);
-
- return(0);
-}
-
-/*************************************************************************
-This function is used either to create a new shared memory area or open an
-existing one, but this does not do the operations necessary with the ip mutex.
-They are performed in com_shm_bind or com_shm_open which call this function. */
-static
-ulint
-com_shm_create_or_open(
-/*===================*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: communications endpoint */
- char* name, /* in: address name */
- ulint len) /* in: address name length */
-{
- os_shm_t shm;
- com_shm_t* map;
- os_event_t event_ne;
- os_event_t event_em;
- char* buf;
-
- ut_ad(ep);
- ut_ad(name);
- ut_ad(len > 0);
-
- buf = mem_alloc(COM_MAX_ADDR_LEN + 20);
-
- ut_memcpy(buf, name, len);
-
- ut_strcpy(buf + len, (char*)"_IBSHM");
-
- shm = os_shm_create(sizeof(com_shm_info_t) + COM_MAX_ADDR_LEN +
- com_shm_endpoint_get_size(ep), buf);
- if (shm == NULL) {
-
- return(COM_ERR_NOT_SPECIFIED);
- }
-
- map = os_shm_map(shm);
-
- if (map == NULL) {
- os_shm_free(shm);
-
- return(COM_ERR_NOT_SPECIFIED);
- }
-
- ut_strcpy(buf + len, (char*)"_IBSHM_EV_NE"),
-
- event_ne = os_event_create(buf);
-
- ut_ad(event_ne);
-
- ut_strcpy(buf + len, (char*)"_IBSHM_EV_EM"),
-
- event_em = os_event_create(buf);
-
- ut_ad(event_em);
-
- ut_a(0); /* event_ne and event_em should be auto events! */
-
- com_shm_endpoint_set_shm(ep, shm);
- com_shm_endpoint_set_map(ep, map);
-
- com_shm_endpoint_set_not_empty(ep, event_ne);
- com_shm_endpoint_set_empty(ep, event_em);
-
- com_shm_endpoint_set_addr(ep, buf);
- com_shm_endpoint_set_addr_len(ep, len);
-
- return(0);
-}
-
-/*************************************************************************
-Opens a shared memory area for communication. */
-static
-ulint
-com_shm_open(
-/*=========*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: communications endpoint */
- char* name, /* in: address name */
- ulint len) /* in: address name length */
-{
- ip_mutex_hdl_t* ip_hdl;
- com_shm_t* map;
- ulint ret;
- char buf[COM_MAX_ADDR_LEN + 20];
-
- ret = com_shm_create_or_open(ep, name, len);
-
- if (ret != 0) {
-
- return(ret);
- }
-
- map = com_shm_endpoint_get_map(ep);
-
- /* Open the interprocess mutex to protect the shared memory area */
-
- ut_memcpy(buf, name, len);
- ut_strcpy(buf + len, (char*)"_IBSHM_MTX");
-
- ret = ip_mutex_open(com_shm_get_ip_mutex(map), buf, &ip_hdl);
-
- if (ret != 0) {
-
- return(COM_ERR_NOT_SPECIFIED);
- }
-
- ep->ip_mutex = ip_hdl;
-
- return(0);
-}
-
-/*************************************************************************
-Creates a shared memory area for communication. */
-
-ulint
-com_shm_bind(
-/*=========*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: communications endpoint */
- char* name, /* in: address name */
- ulint len) /* in: address name length */
-{
- com_shm_t* map;
- ulint ret;
- char buf[COM_MAX_ADDR_LEN + 20];
- ip_mutex_hdl_t* ip_hdl;
-
- if (com_shm_endpoint_get_size(ep) == 0) {
-
- return(COM_ERR_MAX_DATAGRAM_SIZE_NOT_SET);
- }
-
- ret = com_shm_create_or_open(ep, name, len);
-
- if (ret != 0) {
-
- return(ret);
- }
-
- map = com_shm_endpoint_get_map(ep);
-
- /* Create the interprocess mutex to protect the shared memory area */
-
- ut_memcpy(buf, name, len);
- ut_strcpy(buf + len, (char*)"_IBSHM_MTX");
-
- ret = ip_mutex_create(com_shm_get_ip_mutex(map), buf, &ip_hdl);
-
- if (ret != 0) {
-
- return(COM_ERR_NOT_SPECIFIED);
- }
-
- /* This endpoint structure owns the shared memory area */
-
- com_shm_endpoint_set_owns_shm(ep, TRUE);
- ep->ip_mutex = ip_hdl;
-
- mutex_enter(&com_shm_destination_mutex);
-
- /* Increment the count of successful bindings */
-
- com_shm_bind_count++;
-
- mutex_exit(&com_shm_destination_mutex);
-
- com_shm_set_not_empty(map, FALSE);
- com_shm_set_empty_waiters(map, 0);
- com_shm_set_max_len(map, com_shm_endpoint_get_size(ep));
-
- com_shm_set_valid(map, COM_SHM_VALID);
-
- os_event_set(com_shm_endpoint_get_empty(ep));
-
- return(0);
-}
-
-/*************************************************************************
-Waits for a datagram to arrive at an endpoint. */
-
-ulint
-com_shm_recvfrom(
-/*=============*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: communications endpoint */
- byte* buf, /* out: datagram buffer; the buffer is
- supplied by the caller */
- ulint buf_len,/* in: datagram buffer length */
- ulint* len, /* out: datagram length */
- char* from, /* out: address name buffer; the buffer is
- supplied by the caller */
- ulint from_len,/* in: address name buffer length */
- ulint* addr_len)/* out: address name length */
-{
- com_shm_t* map;
- ulint loop_count;
-
- map = com_shm_endpoint_get_map(ep);
-
- loop_count = 0;
-loop:
- com_shm_system_call_count++;
-
- /* NOTE: automatic event */
-
- os_event_wait(com_shm_endpoint_get_not_empty(ep));
-
- loop_count++;
-
- if (loop_count > 1) {
- printf("!!!!!!!!COM_SHM loop count %lu\n", (ulong) loop_count);
- }
-
- ut_ad(loop_count < 2);
-
- com_shm_enter(ep);
-
- if (!com_shm_get_not_empty(map)) {
- /* There was no datagram, wait for the event */
-
- com_shm_exit(ep);
-
- goto loop;
- }
-
- if (com_shm_get_data_len(map) > buf_len) {
-
- com_shm_exit(ep);
-
- return(COM_ERR_DATA_BUFFER_TOO_SMALL);
- }
-
- if (com_shm_get_addr_len(map) > from_len) {
-
- com_shm_exit(ep);
-
- return(COM_ERR_ADDR_BUFFER_TOO_SMALL);
- }
-
- *len = com_shm_get_data_len(map);
- *addr_len = com_shm_get_addr_len(map);
-
- ut_memcpy(buf, com_shm_get_data(map), *len);
- ut_memcpy(from, com_shm_get_addr(map), *addr_len);
-
- com_shm_set_not_empty(map, FALSE);
-
- /* If there may be writers queuing to insert the datagram, signal the
- empty-event */
-
- if (com_shm_get_empty_waiters(map) != 0) {
-
- com_shm_system_call_count++;
-
- os_event_set(com_shm_endpoint_get_empty(ep));
- }
-
- com_shm_exit(ep);
-
- return(0);
-}
-
-/*************************************************************************
-Sends a datagram to the specified destination. */
-
-ulint
-com_shm_sendto(
-/*===========*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: communications endpoint */
- byte* buf, /* in: datagram buffer */
- ulint len, /* in: datagram length */
- char* to, /* in: address name buffer */
- ulint tolen) /* in: address name length */
-{
- com_shm_endpoint_t* ep2;
- com_shm_t* map;
- ulint sender_len;
- ulint ret;
- ulint loop_count;
-
- /* Try first to find from the cached destination addresses */
-
- ep2 = com_shm_destination_cache_search(to, tolen);
-
- if (ep2 == NULL) {
- /* Did not find it in the cache */
- ep2 = com_shm_endpoint_create();
-
- ret = com_shm_open(ep2, to, tolen);
-
- if (ret != 0) {
- com_shm_endpoint_free(ep2);
-
- return(ret);
- }
-
- /* Insert into the cached destination addresses */
-
- com_shm_destination_cache_insert(ep2);
- }
-
- map = com_shm_endpoint_get_map(ep2);
-
- if (com_shm_get_valid(map) != COM_SHM_VALID) {
-
- com_shm_exit(ep2);
-
- return(COM_ERR_DGRAM_NOT_DELIVERED);
- }
-
- if (com_shm_get_max_len(map) < len) {
-
- com_shm_exit(ep2);
-
- return(COM_ERR_DATA_TOO_LONG);
- }
-
- /* Optimistically, we first go to see if the datagram area is empty,
- without waiting for the empty-event */
-
- loop_count = 0;
-loop:
- loop_count++;
-
- if (loop_count > 5) {
- printf("!!!!!!COM_SHM Notempty loop count %lu\n",
- (ulong) loop_count);
- }
-
- ut_ad(loop_count < 100);
-
- com_shm_enter(ep2);
-
- if (com_shm_get_not_empty(map)) {
-
- /* Not empty, we cannot insert a datagram */
-
- com_shm_set_empty_waiters(map,
- 1 + com_shm_get_empty_waiters(map));
- com_shm_exit(ep2);
-
- com_shm_system_call_count++;
-
- /* Wait for the area to become empty */
- /* NOTE: automatic event */
-
- ret = os_event_wait_time(com_shm_endpoint_get_empty(ep2),
- 10000000);
- ut_a(ret == 0);
-
- com_shm_enter(ep2);
-
- com_shm_set_empty_waiters(map,
- com_shm_get_empty_waiters(map) - 1);
- com_shm_exit(ep2);
-
- goto loop;
- }
-
- sender_len = com_shm_endpoint_get_addr_len(ep);
-
- com_shm_set_data_len(map, len);
- com_shm_set_addr_len(map, sender_len);
-
- ut_memcpy(com_shm_get_data(map), buf, len);
- ut_memcpy(com_shm_get_addr(map), com_shm_endpoint_get_addr(ep),
- sender_len);
- com_shm_set_not_empty(map, TRUE);
- com_shm_system_call_count++;
-
- com_shm_exit(ep2);
-
- /* Signal the event */
-
- os_event_set(com_shm_endpoint_get_not_empty(ep2));
-
- return(0);
-}
diff --git a/innobase/com/makefilewin b/innobase/com/makefilewin
deleted file mode 100644
index 0d2d6d45952..00000000000
--- a/innobase/com/makefilewin
+++ /dev/null
@@ -1,12 +0,0 @@
-include ..\include\makefile.i
-
-com.lib: com0com.obj com0shm.obj
- lib -out:..\libs\com.lib com0com.obj com0shm.obj
-
-com0com.obj: com0com.c
- $(CCOM) $(CFL) -c com0com.c
-
-com0shm.obj: com0shm.c
- $(CCOM) $(CFL) -c com0shm.c
-
-
diff --git a/innobase/configure.in b/innobase/configure.in
index 741131eb9e2..652291f1f38 100644
--- a/innobase/configure.in
+++ b/innobase/configure.in
@@ -34,6 +34,7 @@ CXXFLAGS="$CXXFLAGS "
AC_PROG_CC
AC_PROG_RANLIB
AC_PROG_INSTALL
+AC_PROG_LIBTOOL
AC_CHECK_HEADERS(aio.h sched.h)
AC_CHECK_SIZEOF(int, 4)
AC_CHECK_SIZEOF(long, 4)
@@ -112,7 +113,7 @@ case "$target" in
esac
AC_OUTPUT(Makefile os/Makefile ut/Makefile btr/Makefile dnl
- buf/Makefile com/Makefile data/Makefile dnl
+ buf/Makefile data/Makefile dnl
dict/Makefile dyn/Makefile dnl
eval/Makefile fil/Makefile fsp/Makefile fut/Makefile dnl
ha/Makefile ibuf/Makefile include/Makefile dnl
diff --git a/innobase/cry/makefilewin b/innobase/cry/makefilewin
deleted file mode 100644
index 9e791b8d073..00000000000
--- a/innobase/cry/makefilewin
+++ /dev/null
@@ -1,12 +0,0 @@
-include ..\include\makefile.i
-
-doall: cr.exe dcr.exe wro.exe
-
-cr.exe: cry0cry.c
- $(CCOM) $(CFLW) -o cr.exe -I.. cry0cry.c ..\ut.lib ..\os.lib
-
-dcr.exe: cry0dcr.c
- $(CCOM) $(CFLW) -o dcr.exe -I.. cry0dcr.c ..\ut.lib ..\os.lib
-
-wro.exe: cry0wro.c
- $(CCOM) $(CFLW) -o wro.exe -I.. cry0wro.c ..\ut.lib ..\os.lib
diff --git a/innobase/data/data0data.c b/innobase/data/data0data.c
index 9df933c0ac6..0ed0efeb160 100644
--- a/innobase/data/data0data.c
+++ b/innobase/data/data0data.c
@@ -114,8 +114,8 @@ dtuple_datas_are_ordering_equal(
ulint i;
ut_ad(tuple1 && tuple2);
- ut_ad(tuple1->magic_n = DATA_TUPLE_MAGIC_N);
- ut_ad(tuple2->magic_n = DATA_TUPLE_MAGIC_N);
+ ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
+ ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
ut_ad(dtuple_check_typed(tuple1));
ut_ad(dtuple_check_typed(tuple2));
@@ -263,7 +263,7 @@ dfield_check_typed(
(ulong) dfield_get_type(field)->mtype,
(ulong) dfield_get_len(field));
- ut_a(0);
+ ut_error;
}
return(TRUE);
@@ -308,7 +308,7 @@ dtuple_validate(
ulint i;
ulint j;
- ut_a(tuple->magic_n = DATA_TUPLE_MAGIC_N);
+ ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
n_fields = dtuple_get_n_fields(tuple);
diff --git a/innobase/dict/dict0boot.c b/innobase/dict/dict0boot.c
index 76c94d1a918..46cf6c7788d 100644
--- a/innobase/dict/dict0boot.c
+++ b/innobase/dict/dict0boot.c
@@ -39,8 +39,9 @@ dict_hdr_get(
header = DICT_HDR + buf_page_get(DICT_HDR_SPACE, DICT_HDR_PAGE_NO,
RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(header, SYNC_DICT_HEADER);
-
+#endif /* UNIV_SYNC_DEBUG */
return(header);
}
@@ -64,7 +65,7 @@ dict_hdr_get_new_id(
dict_hdr = dict_hdr_get(&mtr);
- id = mtr_read_dulint(dict_hdr + type, MLOG_8BYTES, &mtr);
+ id = mtr_read_dulint(dict_hdr + type, &mtr);
/* Add some dummy code here because otherwise pgcc seems to
compile wrong */
@@ -75,7 +76,7 @@ dict_hdr_get_new_id(
id = ut_dulint_add(id, 1);
- mlog_write_dulint(dict_hdr + type, id, MLOG_8BYTES, &mtr);
+ mlog_write_dulint(dict_hdr + type, id, &mtr);
mtr_commit(&mtr);
@@ -94,7 +95,9 @@ dict_hdr_flush_row_id(void)
dulint id;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
id = dict_sys->row_id;
@@ -102,7 +105,7 @@ dict_hdr_flush_row_id(void)
dict_hdr = dict_hdr_get(&mtr);
- mlog_write_dulint(dict_hdr + DICT_HDR_ROW_ID, id, MLOG_8BYTES, &mtr);
+ mlog_write_dulint(dict_hdr + DICT_HDR_ROW_ID, id, &mtr);
mtr_commit(&mtr);
}
@@ -138,20 +141,16 @@ dict_hdr_create(
/* Start counting row, table, index, and tree ids from
DICT_HDR_FIRST_ID */
mlog_write_dulint(dict_header + DICT_HDR_ROW_ID,
- ut_dulint_create(0, DICT_HDR_FIRST_ID),
- MLOG_8BYTES, mtr);
+ ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
mlog_write_dulint(dict_header + DICT_HDR_TABLE_ID,
- ut_dulint_create(0, DICT_HDR_FIRST_ID),
- MLOG_8BYTES, mtr);
+ ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
mlog_write_dulint(dict_header + DICT_HDR_INDEX_ID,
- ut_dulint_create(0, DICT_HDR_FIRST_ID),
- MLOG_8BYTES, mtr);
+ ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
mlog_write_dulint(dict_header + DICT_HDR_MIX_ID,
- ut_dulint_create(0, DICT_HDR_FIRST_ID),
- MLOG_8BYTES, mtr);
+ ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
/* Create the B-tree roots for the clustered indexes of the basic
system tables */
@@ -247,7 +246,7 @@ dict_boot(void)
dict_sys->row_id = ut_dulint_add(
ut_dulint_align_up(
mtr_read_dulint(dict_hdr + DICT_HDR_ROW_ID,
- MLOG_8BYTES, &mtr),
+ &mtr),
DICT_HDR_ROW_ID_WRITE_MARGIN),
DICT_HDR_ROW_ID_WRITE_MARGIN);
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index ec54bb2d712..6a951317d47 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -158,7 +158,7 @@ dict_create_sys_tables_tuple(
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
dfield_set_data(dfield, table->cluster_name,
ut_strlen(table->cluster_name));
- ut_a(0); /* Oracle-style clusters are not supported yet */
+ ut_error; /* Oracle-style clusters are not supported yet */
} else {
dfield_set_data(dfield, NULL, UNIV_SQL_NULL);
}
@@ -272,9 +272,10 @@ dict_build_table_def_step(
ulint error;
mtr_t mtr;
- UT_NOT_USED(thr);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
+
table = node->table;
table->id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
@@ -369,7 +370,9 @@ dict_create_sys_indexes_tuple(
byte* ptr;
UT_NOT_USED(trx);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(index && heap);
sys_indexes = dict_sys->sys_indexes;
@@ -562,8 +565,9 @@ dict_build_index_def_step(
dict_index_t* index;
dtuple_t* row;
- UT_NOT_USED(thr);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
index = node->index;
@@ -635,8 +639,10 @@ dict_create_index_tree_step(
dtuple_t* search_tuple;
btr_pcur_t pcur;
mtr_t mtr;
-
+
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
UT_NOT_USED(thr);
index = node->index;
@@ -701,7 +707,9 @@ dict_drop_index_tree(
byte* ptr;
ulint len;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ptr = rec_get_nth_field(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
@@ -831,8 +839,10 @@ dict_create_table_step(
trx_t* trx;
ut_ad(thr);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
+
trx = thr_get_trx(thr);
node = thr->run_node;
@@ -939,7 +949,9 @@ dict_create_index_step(
trx_t* trx;
ut_ad(thr);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
trx = thr_get_trx(thr);
@@ -1128,7 +1140,7 @@ dict_create_or_check_foreign_constraint_tables(void)
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
- ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
+ ut_a(thr = que_fork_start_command(graph));
que_run_threads(thr);
@@ -1201,7 +1213,9 @@ dict_create_add_foreigns_to_dictionary(
ulint i;
char buf[10000];
- ut_ad(mutex_own(&(dict_sys->mutex)));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (NULL == dict_table_get_low((char *) "SYS_FOREIGN")) {
fprintf(stderr,
@@ -1262,7 +1276,7 @@ loop:
foreign->referenced_col_names[i]);
}
- ut_a(len < (sizeof buf) - 19)
+ ut_a(len < (sizeof buf) - 19);
len += sprintf(buf + len,"COMMIT WORK;\nEND;\n");
graph = pars_sql(buf);
@@ -1274,7 +1288,7 @@ loop:
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
- ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
+ ut_a(thr = que_fork_start_command(graph));
que_run_threads(thr);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 13ed5bd9af1..cf4b0482aa2 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -209,7 +209,7 @@ dict_tables_have_same_db(
}
}
- ut_a(0);
+ ut_error;
return(FALSE);
}
@@ -232,7 +232,7 @@ dict_remove_db_name(
}
}
- ut_a(0);
+ ut_error;
return(NULL);
}
@@ -255,7 +255,7 @@ dict_get_db_name_len(
}
}
- ut_a(0);
+ ut_error;
return(0);
}
@@ -616,7 +616,9 @@ dict_table_get_on_id(
if we are doing a rollback to handle an error in TABLE
CREATE, for example, we already have the mutex! */
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
return(dict_table_get_on_id_low(table_id, trx));
}
@@ -631,7 +633,7 @@ dict_table_get_on_id(
}
/************************************************************************
-Looks for column n postion in the clustered index. */
+Looks for column n position in the clustered index. */
ulint
dict_table_get_nth_col_pos(
@@ -645,6 +647,44 @@ dict_table_get_nth_col_pos(
n));
}
+/************************************************************************
+Checks if a column is in the ordering columns of the clustered index of a
+table. Column prefixes are treated like whole columns. */
+
+ibool
+dict_table_col_in_clustered_key(
+/*============================*/
+ /* out: TRUE if the column, or its prefix, is
+ in the clustered key */
+ dict_table_t* table, /* in: table */
+ ulint n) /* in: column number */
+{
+ dict_index_t* index;
+ dict_field_t* field;
+ dict_col_t* col;
+ ulint pos;
+ ulint n_fields;
+
+ ut_ad(table);
+
+ col = dict_table_get_nth_col(table, n);
+
+ index = dict_table_get_first_index(table);
+
+ n_fields = dict_index_get_n_unique(index);
+
+ for (pos = 0; pos < n_fields; pos++) {
+ field = dict_index_get_nth_field(index, pos);
+
+ if (col == field->col) {
+
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
/**************************************************************************
Inits the data dictionary module. */
@@ -762,7 +802,9 @@ dict_table_add_to_cache(
ulint i;
ut_ad(table);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
ut_ad(table->cached == FALSE);
@@ -898,8 +940,10 @@ dict_table_rename_in_cache(
ulint i;
ut_ad(table);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
+
old_size = mem_heap_get_size(table->heap);
fold = ut_fold_string(new_name);
@@ -1136,7 +1180,9 @@ dict_table_remove_from_cache(
ulint i;
ut_ad(table);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* printf("Removing table %s from dictionary cache\n", table->name); */
@@ -1205,9 +1251,11 @@ dict_table_LRU_trim(void)
dict_table_t* table;
dict_table_t* prev_table;
- ut_a(0);
+ ut_error;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
table = UT_LIST_GET_LAST(dict_sys->table_LRU);
@@ -1236,7 +1284,9 @@ dict_col_add_to_cache(
ulint fold;
ut_ad(table && col);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
fold = ut_fold_ulint_pair(ut_fold_string(table->name),
@@ -1267,7 +1317,9 @@ dict_col_remove_from_cache(
ulint fold;
ut_ad(table && col);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
fold = ut_fold_ulint_pair(ut_fold_string(table->name),
@@ -1290,7 +1342,9 @@ dict_col_reposition_in_cache(
ulint fold;
ut_ad(table && col);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
fold = ut_fold_ulint_pair(ut_fold_string(table->name),
@@ -1324,7 +1378,9 @@ dict_index_add_to_cache(
ulint i;
ut_ad(index);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(index->n_def == index->n_fields);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
@@ -1450,7 +1506,9 @@ dict_index_remove_from_cache(
ut_ad(table && index);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(UT_LIST_GET_LEN((index->tree)->tree_indexes) == 1);
dict_tree_free(index->tree);
@@ -1494,7 +1552,9 @@ dict_index_find_cols(
ut_ad(table && index);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
for (i = 0; i < index->n_fields; i++) {
field = dict_index_get_nth_field(index, i);
@@ -1635,7 +1695,9 @@ dict_index_build_internal_clust(
ut_ad(table && index);
ut_ad(index->type & DICT_CLUSTERED);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* Create a new index object with certainly enough fields */
@@ -1804,7 +1866,9 @@ dict_index_build_internal_non_clust(
ut_ad(table && index);
ut_ad(0 == (index->type & DICT_CLUSTERED));
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* The clustered index should be the first in the list of indexes */
@@ -1923,7 +1987,9 @@ dict_foreign_remove_from_cache(
/*===========================*/
dict_foreign_t* foreign) /* in, own: foreign constraint */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(foreign);
if (foreign->referenced_table) {
@@ -1952,7 +2018,9 @@ dict_foreign_find(
{
dict_foreign_t* foreign;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
foreign = UT_LIST_GET_FIRST(table->foreign_list);
@@ -2061,7 +2129,9 @@ dict_foreign_add_to_cache(
ibool added_to_referenced_list = FALSE;
char* buf = dict_foreign_err_buf;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
for_table = dict_table_check_if_in_cache_low(
foreign->foreign_table_name);
@@ -2732,7 +2802,9 @@ dict_create_foreign_constraints_low(
ulint column_name_lens[500];
char referenced_table_name[2500];
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
table = dict_table_get_low(name);
@@ -3312,7 +3384,9 @@ dict_foreign_parse_drop_constraints(
str = dict_strip_comments(*(trx->mysql_query_str));
ptr = str;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
loop:
ptr = dict_scan_to(ptr, (char *) "DROP");
@@ -3452,7 +3526,9 @@ dict_procedure_reserve_parsed_copy(
que_t* graph;
proc_node_t* proc_node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(dict_sys->mutex));
@@ -3500,7 +3576,9 @@ dict_procedure_release_parsed_copy(
{
proc_node_t* proc_node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(dict_sys->mutex));
@@ -3577,9 +3655,9 @@ dict_tree_create(
tree->id = index->id;
UT_LIST_INIT(tree->tree_indexes);
-
+#ifdef UNIV_DEBUG
tree->magic_n = DICT_TREE_MAGIC_N;
-
+#endif /* UNIV_DEBUG */
rw_lock_create(&(tree->lock));
rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE);
@@ -3596,7 +3674,7 @@ dict_tree_free(
dict_tree_t* tree) /* in, own: index tree */
{
ut_a(tree);
- ut_a(tree->magic_n == DICT_TREE_MAGIC_N);
+ ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
rw_lock_free(&(tree->lock));
mem_free(tree);
@@ -3990,7 +4068,9 @@ dict_foreign_print_low(
{
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
printf(" FOREIGN KEY CONSTRAINT %s: %s (", foreign->id,
foreign->foreign_table_name);
@@ -4055,7 +4135,9 @@ dict_table_print_low(
dict_foreign_t* foreign;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
dict_update_statistics_low(table, TRUE);
@@ -4109,7 +4191,9 @@ dict_col_print_low(
{
dtype_t* type;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
type = dict_col_get_type(col);
printf("%s: ", col->name);
@@ -4129,7 +4213,9 @@ dict_index_print_low(
ib_longlong n_vals;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
tree = index->tree;
@@ -4175,7 +4261,9 @@ dict_field_print_low(
/*=================*/
dict_field_t* field) /* in: field */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
printf(" %s", field->name);
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index 07c4ef3c683..c6a8ebc4b55 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -43,7 +43,9 @@ dict_get_first_table_name_in_db(
char* table_name;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
heap = mem_heap_create(1000);
@@ -307,7 +309,9 @@ dict_load_columns(
ulint i;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
mtr_start(&mtr);
@@ -414,7 +418,9 @@ dict_load_fields(
ulint i;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
UT_NOT_USED(table);
@@ -526,7 +532,9 @@ dict_load_indexes(
dulint id;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if ((ut_dulint_get_high(table->id) == 0)
&& (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
@@ -700,7 +708,9 @@ dict_load_table(
ulint err;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
heap = mem_heap_create(1000);
@@ -791,7 +801,7 @@ dict_load_table(
table->type = mach_read_from_4(field);
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
- ut_a(0);
+ ut_error;
field = rec_get_nth_field(rec, 6, &len);
table->mix_id = mach_read_from_8(field);
@@ -872,7 +882,9 @@ dict_load_table_on_id(
char* name;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
/* NOTE that the operation of this function is protected by
the dictionary mutex, and therefore no deadlocks can occur
@@ -957,7 +969,9 @@ dict_load_sys_table(
{
mem_heap_t* heap;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
heap = mem_heap_create(1000);
@@ -988,7 +1002,9 @@ dict_load_foreign_cols(
ulint i;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
foreign->n_fields * sizeof(void*));
@@ -1069,7 +1085,9 @@ dict_load_foreign(
ulint err;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
heap2 = mem_heap_create(1000);
@@ -1201,7 +1219,9 @@ dict_load_foreigns(
ulint err;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
sys_foreign = dict_table_get_low((char *) "SYS_FOREIGN");
diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c
index aed44eb246c..c49738a0960 100644
--- a/innobase/dict/dict0mem.c
+++ b/innobase/dict/dict0mem.c
@@ -92,9 +92,9 @@ dict_mem_table_create(
mutex_set_level(&(table->autoinc_mutex), SYNC_DICT_AUTOINC_MUTEX);
table->autoinc_inited = FALSE;
-
+#ifdef UNIV_DEBUG
table->magic_n = DICT_TABLE_MAGIC_N;
-
+#endif /* UNIV_DEBUG */
return(table);
}
@@ -219,7 +219,9 @@ dict_mem_index_create(
index->stat_n_diff_key_vals = NULL;
index->cached = FALSE;
+#ifdef UNIV_DEBUG
index->magic_n = DICT_INDEX_MAGIC_N;
+#endif /* UNIV_DEBUG */
return(index);
}
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index ee63df08744..768dda4eedc 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -534,7 +534,9 @@ fil_node_close_file(
ibool ret;
ut_ad(node && system);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(system->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(node->open);
ut_a(node->n_pending == 0);
ut_a(node->n_pending_flushes == 0);
@@ -742,7 +744,9 @@ fil_node_free(
fil_space_t* space) /* in: space where the file node is chained */
{
ut_ad(node && system && space);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(system->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(node->magic_n == FIL_NODE_MAGIC_N);
ut_a(node->n_pending == 0);
@@ -3383,7 +3387,9 @@ fil_node_prepare_for_io(
fil_space_t* space) /* in: space */
{
ut_ad(node && system && space);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(system->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (system->n_open > system->max_n_open + 5) {
ut_print_timestamp(stderr);
@@ -3427,7 +3433,9 @@ fil_node_complete_io(
{
ut_ad(node);
ut_ad(system);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(system->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(node->n_pending > 0);
@@ -3561,7 +3569,7 @@ fil_io(
space->name, (ulong) byte_offset, (ulong) len,
(ulong) type);
- ut_a(0);
+ ut_error;
}
if (node->size > block_offset) {
@@ -3726,7 +3734,7 @@ fil_aio_wait(
ret = os_aio_posix_handle(segment, &fil_node, &message);
#else
ret = 0; /* Eliminate compiler warning */
- ut_a(0);
+ ut_error;
#endif
} else {
srv_io_thread_op_info[segment] =(char *)"handle simulated aio";
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index 0781da3e223..77535e4c524 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -327,9 +327,9 @@ fsp_get_space_header(
ut_ad(mtr);
header = FSP_HEADER_OFFSET + buf_page_get(id, 0, RW_X_LATCH, mtr);
-
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(header, SYNC_FSP_PAGE);
-
+#endif /* UNIV_SYNC_DEBUG */
return(header);
}
@@ -684,7 +684,9 @@ xdes_get_descriptor_with_space_hdr(
} else {
descr_page = buf_page_get(space, descr_page_no, RW_X_LATCH,
mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(descr_page, SYNC_FSP_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
}
return(descr_page + XDES_ARR_OFFSET
@@ -714,8 +716,9 @@ xdes_get_descriptor(
sp_header = FSP_HEADER_OFFSET
+ buf_page_get(space, 0, RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(sp_header, SYNC_FSP_PAGE);
-
+#endif /* UNIV_SYNC_DEBUG */
return(xdes_get_descriptor_with_space_hdr(sp_header, space, offset,
mtr));
}
@@ -879,9 +882,10 @@ fsp_header_init(
mtr_x_lock(fil_space_get_latch(space), mtr);
page = buf_page_create(space, 0, mtr);
-
buf_page_get(space, 0, RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
/* The prior contents of the file page should be ignored */
@@ -902,8 +906,7 @@ fsp_header_init(
flst_init(header + FSP_SEG_INODES_FULL, mtr);
flst_init(header + FSP_SEG_INODES_FREE, mtr);
- mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1),
- MLOG_8BYTES, mtr);
+ mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr);
if (space == 0) {
fsp_fill_free_list(FALSE, space, header, mtr);
btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, space,
@@ -1244,8 +1247,10 @@ fsp_fill_free_list(
if (i > 0) {
descr_page = buf_page_create(space, i, mtr);
buf_page_get(space, i, RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(descr_page,
SYNC_FSP_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
fsp_init_file_page(descr_page, mtr);
}
@@ -1258,11 +1263,11 @@ fsp_fill_free_list(
ibuf_page = buf_page_create(space,
i + FSP_IBUF_BITMAP_OFFSET, &ibuf_mtr);
-
buf_page_get(space, i + FSP_IBUF_BITMAP_OFFSET,
RW_X_LATCH, &ibuf_mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(ibuf_page, SYNC_FSP_PAGE);
-
+#endif /* UNIV_SYNC_DEBUG */
fsp_init_file_page(ibuf_page, &ibuf_mtr);
ibuf_bitmap_page_init(ibuf_page, &ibuf_mtr);
@@ -1423,7 +1428,7 @@ fsp_alloc_free_page(
ut_print_buf(((byte*)descr) - 500, 1000);
- ut_a(0);
+ ut_error;
}
page_no = xdes_get_offset(descr) + free;
@@ -1478,8 +1483,9 @@ fsp_alloc_free_page(
buf_page_create(space, page_no, mtr);
page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
-
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
/* Prior contents of the page should be ignored */
fsp_init_file_page(page, mtr);
@@ -1529,7 +1535,7 @@ fsp_free_page(
return;
}
- ut_a(0);
+ ut_error;
}
if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)
@@ -1599,7 +1605,7 @@ fsp_free_extent(
ut_print_buf(((byte*)descr) - 500, 1000);
- ut_a(0);
+ ut_error;
}
xdes_init(descr, mtr);
@@ -1714,15 +1720,15 @@ fsp_alloc_seg_inode_page(
buf_block_align(page)->check_index_page_at_flush = FALSE;
fil_page_set_type(page, FIL_PAGE_INODE);
-
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
for (i = 0; i < FSP_SEG_INODES_PER_PAGE; i++) {
inode = fsp_seg_inode_page_get_nth_inode(page, i, mtr);
- mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero,
- MLOG_8BYTES, mtr);
+ mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
}
flst_add_last(space_header + FSP_SEG_INODES_FREE,
@@ -1762,7 +1768,9 @@ fsp_alloc_seg_inode(
page = buf_page_get(buf_frame_get_space_id(space_header), page_no,
RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
n = fsp_seg_inode_page_find_free(page, 0, mtr);
@@ -1815,7 +1823,7 @@ fsp_free_seg_inode(
page + FSEG_INODE_PAGE_NODE, mtr);
}
- mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, MLOG_8BYTES, mtr);
+ mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr);
if (ULINT_UNDEFINED == fsp_seg_inode_page_find_used(page, mtr)) {
@@ -2014,9 +2022,11 @@ fseg_create_general(
mtr);
}
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex)
|| mtr_memo_contains(mtr, fil_space_get_latch(space),
MTR_MEMO_X_LOCK));
+#endif /* UNIV_SYNC_DEBUG */
latch = fil_space_get_latch(space);
mtr_x_lock(latch, mtr);
@@ -2050,12 +2060,12 @@ fseg_create_general(
/* Read the next segment id from space header and increment the
value in space header */
- seg_id = mtr_read_dulint(space_header + FSP_SEG_ID, MLOG_8BYTES, mtr);
+ seg_id = mtr_read_dulint(space_header + FSP_SEG_ID, mtr);
mlog_write_dulint(space_header + FSP_SEG_ID, ut_dulint_add(seg_id, 1),
- MLOG_8BYTES, mtr);
+ mtr);
- mlog_write_dulint(inode + FSEG_ID, seg_id, MLOG_8BYTES, mtr);
+ mlog_write_dulint(inode + FSEG_ID, seg_id, mtr);
mlog_write_ulint(inode + FSEG_NOT_FULL_N_USED, 0, MLOG_4BYTES, mtr);
flst_init(inode + FSEG_FREE, mtr);
@@ -2170,9 +2180,11 @@ fseg_n_reserved_pages(
space = buf_frame_get_space_id(header);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex)
|| mtr_memo_contains(mtr, fil_space_get_latch(space),
MTR_MEMO_X_LOCK));
+#endif /* UNIV_SYNC_DEBUG */
mtr_x_lock(fil_space_get_latch(space), mtr);
inode = fseg_inode_get(header, mtr);
@@ -2235,8 +2247,8 @@ fseg_fill_free_list(
xdes_set_state(descr, XDES_FSEG, mtr);
- seg_id = mtr_read_dulint(inode + FSEG_ID, MLOG_8BYTES, mtr);
- mlog_write_dulint(descr + XDES_ID, seg_id, MLOG_8BYTES, mtr);
+ seg_id = mtr_read_dulint(inode + FSEG_ID, mtr);
+ mlog_write_dulint(descr + XDES_ID, seg_id, mtr);
flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
hint += FSP_EXTENT_SIZE;
@@ -2277,10 +2289,10 @@ fseg_alloc_free_extent(
return(NULL);
}
- seg_id = mtr_read_dulint(inode + FSEG_ID, MLOG_8BYTES, mtr);
+ seg_id = mtr_read_dulint(inode + FSEG_ID, mtr);
xdes_set_state(descr, XDES_FSEG, mtr);
- mlog_write_dulint(descr + XDES_ID, seg_id, MLOG_8BYTES, mtr);
+ mlog_write_dulint(descr + XDES_ID, seg_id, mtr);
flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
/* Try to fill the segment free list */
@@ -2330,7 +2342,7 @@ fseg_alloc_free_page_low(
ut_ad((direction >= FSP_UP) && (direction <= FSP_NO_DIR));
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) ==
FSEG_MAGIC_N_VALUE);
- seg_id = mtr_read_dulint(seg_inode + FSEG_ID, MLOG_8BYTES, mtr);
+ seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr);
ut_ad(ut_dulint_cmp(seg_id, ut_dulint_zero) > 0);
@@ -2351,8 +2363,7 @@ fseg_alloc_free_page_low(
/*-------------------------------------------------------------*/
if ((xdes_get_state(descr, mtr) == XDES_FSEG)
&& (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID,
- MLOG_8BYTES, mtr),
- seg_id))
+ mtr), seg_id))
&& (xdes_get_bit(descr, XDES_FREE_BIT,
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
@@ -2374,8 +2385,7 @@ fseg_alloc_free_page_low(
ut_a(ret_descr == descr);
xdes_set_state(ret_descr, XDES_FSEG, mtr);
- mlog_write_dulint(ret_descr + XDES_ID, seg_id, MLOG_8BYTES,
- mtr);
+ mlog_write_dulint(ret_descr + XDES_ID, seg_id, mtr);
flst_add_last(seg_inode + FSEG_FREE,
ret_descr + XDES_FLST_NODE, mtr);
@@ -2404,8 +2414,7 @@ fseg_alloc_free_page_low(
/*-------------------------------------------------------------*/
} else if ((xdes_get_state(descr, mtr) == XDES_FSEG)
&& (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID,
- MLOG_8BYTES, mtr),
- seg_id))
+ mtr), seg_id))
&& (!xdes_is_full(descr, mtr))) {
/* 4. We can take the page from the same extent as the
@@ -2506,7 +2515,9 @@ fseg_alloc_free_page_low(
ut_a(page == buf_page_get(space, ret_page, RW_X_LATCH, mtr));
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
/* The prior contents of the page should be ignored */
fsp_init_file_page(page, mtr);
@@ -2560,9 +2571,11 @@ fseg_alloc_free_page_general(
space = buf_frame_get_space_id(seg_header);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex)
|| mtr_memo_contains(mtr, fil_space_get_latch(space),
MTR_MEMO_X_LOCK));
+#endif /* UNIV_SYNC_DEBUG */
latch = fil_space_get_latch(space);
mtr_x_lock(latch, mtr);
@@ -2708,9 +2721,11 @@ fsp_reserve_free_extents(
ulint n_pages_added;
ut_ad(mtr);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex)
|| mtr_memo_contains(mtr, fil_space_get_latch(space),
MTR_MEMO_X_LOCK));
+#endif /* UNIV_SYNC_DEBUG */
*n_reserved = n_ext;
latch = fil_space_get_latch(space);
@@ -2808,8 +2823,9 @@ fsp_get_available_space_in_free_extents(
rw_lock_t* latch;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
-
+#endif /* UNIV_SYNC_DEBUG */
mtr_start(&mtr);
latch = fil_space_get_latch(space);
@@ -2963,7 +2979,7 @@ fseg_free_page_low(
fprintf(stderr,
"InnoDB: If the InnoDB recovery crashes here, see section 6.1\n"
"InnoDB: of http://www.innodb.com/ibman.html about forcing recovery.\n");
- ut_a(0);
+ ut_error;
}
state = xdes_get_state(descr, mtr);
@@ -2988,8 +3004,8 @@ fseg_free_page_low(
/* If we get here, the page is in some extent of the segment */
- descr_id = mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES, mtr);
- seg_id = mtr_read_dulint(seg_inode + FSEG_ID, MLOG_8BYTES, mtr);
+ descr_id = mtr_read_dulint(descr + XDES_ID, mtr);
+ seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr);
/*
fprintf(stderr,
"InnoDB: InnoDB is freeing space %lu page %lu,\n"
@@ -3022,7 +3038,7 @@ fseg_free_page_low(
fprintf(stderr,
"InnoDB: If the InnoDB recovery crashes here, see section 6.1\n"
"InnoDB: of http://www.innodb.com/ibman.html about forcing recovery.\n");
- ut_a(0);
+ ut_error;
}
not_full_n_used = mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
@@ -3066,9 +3082,11 @@ fseg_free_page(
{
fseg_inode_t* seg_inode;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex)
|| mtr_memo_contains(mtr, fil_space_get_latch(space),
MTR_MEMO_X_LOCK));
+#endif /* UNIV_SYNC_DEBUG */
mtr_x_lock(fil_space_get_latch(space), mtr);
seg_inode = fseg_inode_get(seg_header, mtr);
@@ -3103,8 +3121,8 @@ fseg_free_extent(
ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES, mtr),
- mtr_read_dulint(seg_inode + FSEG_ID, MLOG_8BYTES, mtr)));
+ mtr_read_dulint(descr + XDES_ID, mtr),
+ mtr_read_dulint(seg_inode + FSEG_ID, mtr)));
first_page_in_extent = page - (page % FSP_EXTENT_SIZE);
@@ -3175,9 +3193,11 @@ fseg_free_step(
space = buf_frame_get_space_id(header);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex)
|| mtr_memo_contains(mtr, fil_space_get_latch(space),
MTR_MEMO_X_LOCK));
+#endif /* UNIV_SYNC_DEBUG */
mtr_x_lock(fil_space_get_latch(space), mtr);
descr = xdes_get_descriptor(space, buf_frame_get_page_no(header), mtr);
@@ -3248,9 +3268,11 @@ fseg_free_step_not_header(
space = buf_frame_get_space_id(header);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex)
|| mtr_memo_contains(mtr, fil_space_get_latch(space),
MTR_MEMO_X_LOCK));
+#endif /* UNIV_SYNC_DEBUG */
mtr_x_lock(fil_space_get_latch(space), mtr);
inode = fseg_inode_get(header, mtr);
@@ -3392,7 +3414,7 @@ fseg_validate_low(
space = buf_frame_get_space_id(inode);
- seg_id = mtr_read_dulint(inode + FSEG_ID, MLOG_8BYTES, mtr2);
+ seg_id = mtr_read_dulint(inode + FSEG_ID, mtr2);
n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
MLOG_4BYTES, mtr2);
flst_validate(inode + FSEG_FREE, mtr2);
@@ -3411,8 +3433,7 @@ fseg_validate_low(
ut_a(xdes_get_n_used(descr, &mtr) == 0);
ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES,
- &mtr), seg_id));
+ mtr_read_dulint(descr + XDES_ID, &mtr), seg_id));
node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
mtr_commit(&mtr);
@@ -3432,8 +3453,7 @@ fseg_validate_low(
ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE);
ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES,
- &mtr), seg_id));
+ mtr_read_dulint(descr + XDES_ID, &mtr), seg_id));
n_used2 += xdes_get_n_used(descr, &mtr);
@@ -3454,8 +3474,7 @@ fseg_validate_low(
ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE);
ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
ut_a(0 == ut_dulint_cmp(
- mtr_read_dulint(descr + XDES_ID, MLOG_8BYTES,
- &mtr), seg_id));
+ mtr_read_dulint(descr + XDES_ID, &mtr), seg_id));
node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
mtr_commit(&mtr);
@@ -3520,7 +3539,7 @@ fseg_print_low(
reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
- d_var = mtr_read_dulint(inode + FSEG_ID, MLOG_8BYTES, mtr);
+ d_var = mtr_read_dulint(inode + FSEG_ID, mtr);
seg_id_low = ut_dulint_get_low(d_var);
seg_id_high = ut_dulint_get_high(d_var);
@@ -3838,7 +3857,7 @@ fsp_print(
n_free_frag = flst_get_len(header + FSP_FREE_FRAG, &mtr);
n_full_frag = flst_get_len(header + FSP_FULL_FRAG, &mtr);
- d_var = mtr_read_dulint(header + FSP_SEG_ID, MLOG_8BYTES, &mtr);
+ d_var = mtr_read_dulint(header + FSP_SEG_ID, &mtr);
seg_id_low = ut_dulint_get_low(d_var);
seg_id_high = ut_dulint_get_high(d_var);
diff --git a/innobase/ha/ha0ha.c b/innobase/ha/ha0ha.c
index 32d50b5546e..5e807406ce0 100644
--- a/innobase/ha/ha0ha.c
+++ b/innobase/ha/ha0ha.c
@@ -89,8 +89,9 @@ ha_insert_for_fold(
ulint hash;
ut_ad(table && data);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
-
+#endif /* UNIV_SYNC_DEBUG */
hash = hash_calc_hash(fold, table);
cell = hash_get_nth_cell(table, hash);
@@ -186,8 +187,9 @@ ha_delete(
{
ha_node_t* node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
-
+#endif /* UNIV_SYNC_DEBUG */
node = ha_search_with_data(table, fold, data);
ut_a(node);
@@ -237,8 +239,9 @@ ha_remove_all_nodes_to_page(
{
ha_node_t* node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
-
+#endif /* UNIV_SYNC_DEBUG */
node = ha_chain_get_first(table, fold);
while (node) {
diff --git a/innobase/ha/hash0hash.c b/innobase/ha/hash0hash.c
index facdea66198..372104e54b3 100644
--- a/innobase/ha/hash0hash.c
+++ b/innobase/ha/hash0hash.c
@@ -22,6 +22,7 @@ hash_mutex_enter(
hash_table_t* table, /* in: hash table */
ulint fold) /* in: fold */
{
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
mutex_enter(hash_get_mutex(table, fold));
}
@@ -34,41 +35,10 @@ hash_mutex_exit(
hash_table_t* table, /* in: hash table */
ulint fold) /* in: fold */
{
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
mutex_exit(hash_get_mutex(table, fold));
}
-/****************************************************************
-Reserves all the mutexes of a hash table, in an ascending order. */
-
-void
-hash_mutex_enter_all(
-/*=================*/
- hash_table_t* table) /* in: hash table */
-{
- ulint i;
-
- for (i = 0; i < table->n_mutexes; i++) {
-
- mutex_enter(table->mutexes + i);
- }
-}
-
-/****************************************************************
-Releases all the mutexes of a hash table. */
-
-void
-hash_mutex_exit_all(
-/*================*/
- hash_table_t* table) /* in: hash table */
-{
- ulint i;
-
- for (i = 0; i < table->n_mutexes; i++) {
-
- mutex_exit(table->mutexes + i);
- }
-}
-
/*****************************************************************
Creates a hash table with >= n array cells. The actual number of cells is
chosen to be a prime number slightly bigger than n. */
@@ -98,7 +68,9 @@ hash_create(
table->mutexes = NULL;
table->heaps = NULL;
table->heap = NULL;
+#ifdef UNIV_DEBUG
table->magic_n = HASH_TABLE_MAGIC_N;
+#endif /* UNIV_DEBUG */
/* Initialize the cell array */
@@ -119,6 +91,7 @@ hash_table_free(
/*============*/
hash_table_t* table) /* in, own: hash table */
{
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_a(table->mutexes == NULL);
ut_free(table->array);
@@ -140,6 +113,7 @@ hash_create_mutexes(
ulint i;
ut_a(n_mutexes == ut_2_power_up(n_mutexes));
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t));
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index 805f08af361..42ca34e7f10 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -270,7 +270,9 @@ ibuf_header_page_get(
page = buf_page_get(space, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_IBUF_HEADER);
+#endif /* UNIV_SYNC_DEBUG */
return(page);
}
@@ -295,7 +297,9 @@ ibuf_tree_root_get(
page = buf_page_get(space, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH,
mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
+#endif /* UNIV_SYNC_DEBUG */
return(page);
}
@@ -407,7 +411,9 @@ ibuf_data_sizes_update(
{
ulint old_size;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&ibuf_mutex));
+#endif /* UNIV_SYNC_DEBUG */
old_size = data->size;
@@ -489,7 +495,9 @@ ibuf_data_init_for_space(
root = buf_page_get(space, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH,
&mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(root, SYNC_TREE_NODE);
+#endif /* UNIV_SYNC_DEBUG */
data->size = 0;
data->n_inserts = 0;
@@ -721,7 +729,9 @@ ibuf_bitmap_get_map_page(
page = buf_page_get(space, ibuf_bitmap_page_no_calc(page_no),
RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_IBUF_BITMAP);
+#endif /* UNIV_SYNC_DEBUG */
return(page);
}
@@ -1446,7 +1456,9 @@ ibuf_data_enough_free_for_insert(
/* out: TRUE if enough free pages in list */
ibuf_data_t* data) /* in: ibuf data for the space */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&ibuf_mutex));
+#endif /* UNIV_SYNC_DEBUG */
/* We want a big margin of free pages, because a B-tree can sometimes
grow in size also if records are deleted from it, as the node pointers
@@ -1472,7 +1484,9 @@ ibuf_data_too_much_free(
/* out: TRUE if enough free pages in list */
ibuf_data_t* data) /* in: ibuf data for the space */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&ibuf_mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (data->free_list_len >= 3 + data->size / 2 + 3 * data->height) {
@@ -1532,7 +1546,9 @@ ibuf_add_free_page(
page = buf_page_get(space, page_no, RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE_NEW);
+#endif /* UNIV_SYNC_DEBUG */
ibuf_enter();
@@ -1653,7 +1669,9 @@ ibuf_remove_free_page(
page = buf_page_get(space, page_no, RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
+#endif /* UNIV_SYNC_DEBUG */
/* Remove the page from the free list and update the ibuf size data */
@@ -1694,14 +1712,16 @@ ibuf_free_excess_pages(
{
ibuf_data_t* ibuf_data;
ulint i;
-
+
if (space != 0) {
fprintf(stderr,
"InnoDB: Error: calling ibuf_free_excess_pages for space %lu\n", (ulong) space);
return;
}
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(fil_space_get_latch(space), RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(rw_lock_get_x_lock_count(fil_space_get_latch(space)) == 1);
ut_ad(!ibuf_inside());
@@ -2208,7 +2228,9 @@ ibuf_get_volume_buffered(
prev_page = buf_page_get(0, prev_page_no, RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(prev_page, SYNC_TREE_NODE);
+#endif /* UNIV_SYNC_DEBUG */
rec = page_get_supremum_rec(prev_page);
rec = page_rec_get_prev(rec);
@@ -2269,7 +2291,9 @@ count_later:
next_page = buf_page_get(0, next_page_no, RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(next_page, SYNC_TREE_NODE);
+#endif /* UNIV_SYNC_DEBUG */
rec = page_get_infimum_rec(next_page);
rec = page_rec_get_next(rec);
@@ -3018,7 +3042,9 @@ loop:
IB__FILE__, __LINE__,
&mtr);
ut_a(success);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
+#endif /* UNIV_SYNC_DEBUG */
}
/* Position pcur in the insert buffer at the first entry for this
@@ -3261,7 +3287,9 @@ ibuf_validate_low(void)
ibuf_data_t* data;
ulint sum_sizes;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&ibuf_mutex));
+#endif /* UNIV_SYNC_DEBUG */
sum_sizes = 0;
diff --git a/innobase/include/Makefile.am b/innobase/include/Makefile.am
index ab1f14d0770..2584357e24a 100644
--- a/innobase/include/Makefile.am
+++ b/innobase/include/Makefile.am
@@ -18,21 +18,20 @@
noinst_HEADERS = btr0btr.h btr0btr.ic btr0cur.h btr0cur.ic \
btr0pcur.h btr0pcur.ic btr0sea.h btr0sea.ic btr0types.h \
buf0buf.h buf0buf.ic buf0flu.h buf0flu.ic buf0lru.h \
- buf0lru.ic buf0rea.h buf0types.h com0com.h com0com.ic \
- com0shm.h com0shm.ic data0data.h data0data.ic data0type.h \
+ buf0lru.ic buf0rea.h buf0types.h data0data.h data0data.ic data0type.h \
data0type.ic data0types.h db0err.h dict0boot.h \
dict0boot.ic dict0crea.h dict0crea.ic dict0dict.h \
dict0dict.ic dict0load.h dict0load.ic dict0mem.h \
dict0mem.ic dict0types.h dyn0dyn.h dyn0dyn.ic eval0eval.h \
eval0eval.ic eval0proc.h eval0proc.ic fil0fil.h fsp0fsp.h \
fsp0fsp.ic fut0fut.h fut0fut.ic fut0lst.h fut0lst.ic \
- ha0ha.h ha0ha.ic hash0hash.h hash0hash.ic ib_odbc.h \
+ ha0ha.h ha0ha.ic hash0hash.h hash0hash.ic \
ibuf0ibuf.h ibuf0ibuf.ic ibuf0types.h lock0lock.h \
lock0lock.ic lock0types.h log0log.h log0log.ic log0recv.h \
log0recv.ic mach0data.h mach0data.ic makefilewin.i \
mem0dbg.h mem0dbg.ic mem0mem.h mem0mem.ic mem0pool.h \
mem0pool.ic mtr0log.h mtr0log.ic mtr0mtr.h mtr0mtr.ic \
- mtr0types.h odbc0odbc.h os0file.h os0proc.h os0proc.ic \
+ mtr0types.h os0file.h os0proc.h os0proc.ic \
os0shm.h os0shm.ic os0sync.h os0sync.ic os0thread.h \
os0thread.ic page0cur.h page0cur.ic page0page.h \
page0page.ic page0types.h pars0grm.h pars0opt.h \
diff --git a/innobase/include/btr0btr.ic b/innobase/include/btr0btr.ic
index 301a73b3444..b0aa0756307 100644
--- a/innobase/include/btr0btr.ic
+++ b/innobase/include/btr0btr.ic
@@ -45,8 +45,7 @@ btr_page_set_index_id(
dulint id, /* in: index id */
mtr_t* mtr) /* in: mtr */
{
- mlog_write_dulint(page + PAGE_HEADER + PAGE_INDEX_ID, id,
- MLOG_8BYTES, mtr);
+ mlog_write_dulint(page + PAGE_HEADER + PAGE_INDEX_ID, id, mtr);
}
/******************************************************************
diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h
index 221f479df40..f1334656d53 100644
--- a/innobase/include/btr0cur.h
+++ b/innobase/include/btr0cur.h
@@ -435,16 +435,6 @@ btr_cur_mark_dtuple_inherited_extern(
ulint n_ext_vec, /* in: number of elements in ext_vec */
upd_t* update); /* in: update vector */
/***********************************************************************
-Marks all extern fields in a record as owned by the record. This function
-should be called if the delete mark of a record is removed: a not delete
-marked record always owns all its extern fields. */
-
-void
-btr_cur_unmark_extern_fields(
-/*=========================*/
- rec_t* rec, /* in: record in a clustered index */
- mtr_t* mtr); /* in: mtr */
-/***********************************************************************
Marks all extern fields in a dtuple as owned by the record. */
void
diff --git a/innobase/include/btr0sea.h b/innobase/include/btr0sea.h
index 68396d47193..ce4140ecf92 100644
--- a/innobase/include/btr0sea.h
+++ b/innobase/include/btr0sea.h
@@ -214,7 +214,9 @@ extern rw_lock_t* btr_search_latch_temp;
#define btr_search_latch (*btr_search_latch_temp)
+#ifdef UNIV_SEARCH_PERF_STAT
extern ulint btr_search_n_succ;
+#endif /* UNIV_SEARCH_PERF_STAT */
extern ulint btr_search_n_hash_fail;
/* After change in n_fields or n_bytes in info, this many rounds are waited
diff --git a/innobase/include/btr0sea.ic b/innobase/include/btr0sea.ic
index 63a3a658cf4..8a41042f713 100644
--- a/innobase/include/btr0sea.ic
+++ b/innobase/include/btr0sea.ic
@@ -44,8 +44,10 @@ btr_search_info_update(
{
btr_search_t* info;
- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)
- && !rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+ ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
info = btr_search_get_info(index);
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index 3f2fd5bbbe0..3cab717546a 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -562,11 +562,11 @@ buf_awe_map_page_to_frame(
we need to map the page should also
add the block to the
awe_LRU_free_mapped list */
+#ifdef UNIV_SYNC_DEBUG
/*************************************************************************
Adds latch level info for the rw-lock protecting the buffer frame. This
should be called in the debug version after a successful latching of a
-page if we know the latching order level of the acquired latch. If
-UNIV_SYNC_DEBUG is not defined, compiles to an empty function. */
+page if we know the latching order level of the acquired latch. */
UNIV_INLINE
void
buf_page_dbg_add_level(
@@ -574,6 +574,7 @@ buf_page_dbg_add_level(
buf_frame_t* frame, /* in: buffer page where we have acquired
a latch */
ulint level); /* in: latching order level */
+#endif /* UNIV_SYNC_DEBUG */
/*************************************************************************
Gets a pointer to the memory frame of a block. */
UNIV_INLINE
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index 0df8570e4e2..cb54785128f 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -130,7 +130,9 @@ buf_pool_clock_tic(void)
/*====================*/
/* out: new clock value */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
buf_pool->ulint_clock++;
@@ -221,7 +223,7 @@ buf_block_align(
"InnoDB: how to force recovery.\n",
(long)ptr, (long)frame_zero,
(long)(buf_pool->high_end));
- ut_a(0);
+ ut_error;
}
block = *(buf_pool->blocks_of_frames + (((ulint)(ptr - frame_zero))
@@ -257,7 +259,7 @@ buf_frame_align(
"InnoDB: how to force recovery.\n",
(long)ptr, (long)(buf_pool->frame_zero),
(long)(buf_pool->high_end));
- ut_a(0);
+ ut_error;
}
return(frame);
@@ -447,8 +449,10 @@ buf_frame_modify_clock_inc(
block = buf_block_align(frame);
+#ifdef UNIV_SYNC_DEBUG
ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
+#endif /*UNIV_SYNC_DEBUG */
UT_DULINT_INC(block->modify_clock);
@@ -466,8 +470,10 @@ buf_block_modify_clock_inc(
/* out: new value */
buf_block_t* block) /* in: block */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad((mutex_own(&(buf_pool->mutex)) && (block->buf_fix_count == 0))
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
+#endif /* UNIV_SYNC_DEBUG */
UT_DULINT_INC(block->modify_clock);
@@ -490,8 +496,10 @@ buf_frame_get_modify_clock(
block = buf_block_align(frame);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
+#endif /* UNIV_SYNC_DEBUG */
return(block->modify_clock);
}
@@ -542,7 +550,9 @@ buf_page_hash_get(
ulint fold;
ut_ad(buf_pool);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
/* Look for the page in the hash table */
@@ -642,6 +652,7 @@ buf_page_release(
}
}
+#ifdef UNIV_SYNC_DEBUG
/*************************************************************************
Adds latch level info for the rw-lock protecting the buffer frame. This
should be called in the debug version after a successful latching of a
@@ -656,7 +667,6 @@ buf_page_dbg_add_level(
ulint level __attribute__((unused))) /* in: latching order
level */
{
-#ifdef UNIV_SYNC_DEBUG
sync_thread_add_level(&(buf_block_align(frame)->lock), level);
-#endif
}
+#endif /* UNIV_SYNC_DEBUG */
diff --git a/innobase/include/buf0flu.ic b/innobase/include/buf0flu.ic
index e2faf773cab..d6dbdcc0865 100644
--- a/innobase/include/buf0flu.ic
+++ b/innobase/include/buf0flu.ic
@@ -40,8 +40,10 @@ buf_flush_note_modification(
ut_ad(block);
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(block->buf_fix_count > 0);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(ut_dulint_cmp(mtr->start_lsn, ut_dulint_zero) != 0);
ut_ad(mtr->modifications);
@@ -76,7 +78,9 @@ buf_flush_recv_note_modification(
ut_ad(block);
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(block->buf_fix_count > 0);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(buf_pool->mutex));
diff --git a/innobase/include/com0com.h b/innobase/include/com0com.h
deleted file mode 100644
index 6f04b6a3f11..00000000000
--- a/innobase/include/com0com.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/******************************************************
-The communication primitives
-
-(c) 1995 Innobase Oy
-
-Created 9/23/1995 Heikki Tuuri
-*******************************************************/
-
-/* This module defines a standard datagram communication
-function interface for use in the database. We assume that
-the communication medium is reliable. */
-
-#ifndef com0com_h
-#define com0com_h
-
-#include "univ.i"
-
-/* The communications endpoint type definition */
-typedef struct com_endpoint_struct com_endpoint_t;
-
-/* Possible endpoint communication types */
-#define COM_SHM 1 /* communication through shared memory */
-
-/* Option numbers for endpoint */
-#define COM_OPT_MAX_DGRAM_SIZE 1
-
-/* Error numbers */
-#define COM_ERR_NOT_SPECIFIED 1
-#define COM_ERR_NOT_BOUND 2
-#define COM_ERR_ALREADY_BOUND 3
-#define COM_ERR_MAX_DATAGRAM_SIZE_NOT_SET 4
-#define COM_ERR_DATA_BUFFER_TOO_SMALL 5
-#define COM_ERR_ADDR_BUFFER_TOO_SMALL 6
-#define COM_ERR_DATA_TOO_LONG 7
-#define COM_ERR_ADDR_TOO_LONG 8
-#define COM_ERR_DGRAM_NOT_DELIVERED 9
-
-/* Maximum allowed address length in bytes */
-#define COM_MAX_ADDR_LEN 100
-
-/*************************************************************************
-Creates a communications endpoint. */
-
-com_endpoint_t*
-com_endpoint_create(
-/*================*/
- /* out, own: communications endpoint, NULL if
- did not succeed */
- ulint type); /* in: communication type of endpoint:
- only COM_SHM supported */
-/*************************************************************************
-Frees a communications endpoint. */
-
-ulint
-com_endpoint_free(
-/*==============*/
- /* out: O if succeed, else error number */
- com_endpoint_t* ep); /* in, own: communications endpoint */
-/*************************************************************************
-Sets an option, like the maximum datagram size for an endpoint.
-The options may vary depending on the endpoint type. */
-
-ulint
-com_endpoint_set_option(
-/*====================*/
- /* out: 0 if succeed, else error number */
- com_endpoint_t* ep, /* in: endpoint */
- ulint optno, /* in: option number, only
- COM_OPT_MAX_DGRAM_SIZE currently supported */
- byte* optval, /* in: pointer to a buffer containing the
- option value to set */
- ulint optlen);/* in: option value buffer length */
-/*************************************************************************
-Binds a communications endpoint to a specified address. */
-
-ulint
-com_bind(
-/*=====*/
- /* out: 0 if succeed, else error number */
- com_endpoint_t* ep, /* in: communications endpoint */
- char* name, /* in: address name */
- ulint len); /* in: name length */
-/*************************************************************************
-Waits for a datagram to arrive at an endpoint. */
-
-ulint
-com_recvfrom(
-/*=========*/
- /* out: 0 if succeed, else error number */
- com_endpoint_t* ep, /* in: communications endpoint */
- byte* buf, /* out: datagram buffer; the buffer must be
- supplied by the caller */
- ulint buf_len,/* in: datagram buffer length */
- ulint* len, /* out: datagram length */
- char* from, /* out: address name buffer; the buffer must be
- supplied by the caller */
- ulint from_len,/* in: address name buffer length */
- ulint* addr_len);/* out: address name length */
-/*************************************************************************
-Sends a datagram to a specified destination. */
-
-ulint
-com_sendto(
-/*=======*/
- /* out: 0 if succeed, else error number */
- com_endpoint_t* ep, /* in: communications endpoint */
- byte* buf, /* in: datagram buffer */
- ulint len, /* in: datagram length */
- char* to, /* in: address name buffer */
- ulint tolen); /* in: address name length */
-/*************************************************************************
-Gets the maximum datagram size for an endpoint. */
-
-ulint
-com_endpoint_get_max_size(
-/*======================*/
- /* out: maximum size */
- com_endpoint_t* ep); /* in: endpoint */
-
-
-#ifndef UNIV_NONINL
-#include "com0com.ic"
-#endif
-
-#endif
diff --git a/innobase/include/com0com.ic b/innobase/include/com0com.ic
deleted file mode 100644
index cec1cb190cc..00000000000
--- a/innobase/include/com0com.ic
+++ /dev/null
@@ -1,7 +0,0 @@
-/******************************************************
-The communication primitives
-
-(c) 1995 Innobase Oy
-
-Created 9/23/1995 Heikki Tuuri
-*******************************************************/
diff --git a/innobase/include/com0shm.h b/innobase/include/com0shm.h
deleted file mode 100644
index 7de9c4ac2de..00000000000
--- a/innobase/include/com0shm.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/******************************************************
-The communication through shared memory
-
-(c) 1995 Innobase Oy
-
-Created 9/23/1995 Heikki Tuuri
-*******************************************************/
-
-#ifndef com0shm_h
-#define com0shm_h
-
-#include "univ.i"
-
-typedef struct com_shm_endpoint_struct com_shm_endpoint_t;
-
-/* The performance of communication in NT depends on how
-many times a system call is made (excluding os_thread_yield,
-as that is the fastest way to switch thread).
-The following variable counts such events. */
-
-extern ulint com_shm_system_call_count;
-
-
-/*************************************************************************
-Creates a communications endpoint. */
-
-com_shm_endpoint_t*
-com_shm_endpoint_create(void);
-/*=========================*/
- /* out, own: communications endpoint, NULL if
- did not succeed */
-/*************************************************************************
-Frees a communications endpoint. */
-
-ulint
-com_shm_endpoint_free(
-/*==================*/
- /* out: O if succeed, else error number */
- com_shm_endpoint_t* ep);/* in, own: communications endpoint */
-/*************************************************************************
-Sets an option, like the maximum datagram size for an endpoint.
-The options may vary depending on the endpoint type. */
-
-ulint
-com_shm_endpoint_set_option(
-/*========================*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: endpoint */
- ulint optno, /* in: option number, only
- COM_OPT_MAX_DGRAM_SIZE currently supported */
- byte* optval, /* in: pointer to a buffer containing the
- option value to set */
- ulint optlen);/* in: option value buffer length */
-/*************************************************************************
-Bind a communications endpoint to a specified address. */
-
-ulint
-com_shm_bind(
-/*=========*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: communications endpoint */
- char* name, /* in: address name */
- ulint len); /* in: address name length */
-/*************************************************************************
-Waits for a datagram to arrive at an endpoint. */
-
-ulint
-com_shm_recvfrom(
-/*=============*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: communications endpoint */
- byte* buf, /* out: datagram buffer; the buffer is
- supplied by the caller */
- ulint buf_len,/* in: datagram buffer length */
- ulint* len, /* out: datagram length */
- char* from, /* out: address name buffer; the buffer is
- supplied by the caller */
- ulint from_len,/* in: address name buffer length */
- ulint* addr_len);/* out: address name length */
-/*************************************************************************
-Sends a datagram to the specified destination. */
-
-ulint
-com_shm_sendto(
-/*===========*/
- /* out: 0 if succeed, else error number */
- com_shm_endpoint_t* ep, /* in: communications endpoint */
- byte* buf, /* in: datagram buffer */
- ulint len, /* in: datagram length */
- char* to, /* in: address name buffer */
- ulint tolen); /* in: address name length */
-
-ulint
-com_shm_endpoint_get_size(
-/*======================*/
- com_shm_endpoint_t* ep);
-
-
-#ifndef UNIV_NONINL
-#include "com0shm.ic"
-#endif
-
-#endif
diff --git a/innobase/include/com0shm.ic b/innobase/include/com0shm.ic
deleted file mode 100644
index e0d3cb26f69..00000000000
--- a/innobase/include/com0shm.ic
+++ /dev/null
@@ -1,7 +0,0 @@
-/******************************************************
-Communication through shared memory
-
-(c) 1995 Innobase Oy
-
-Created 9/23/1995 Heikki Tuuri
-*******************************************************/
diff --git a/innobase/include/data0data.h b/innobase/include/data0data.h
index 2501d2b809f..c4e93bec738 100644
--- a/innobase/include/data0data.h
+++ b/innobase/include/data0data.h
@@ -402,9 +402,11 @@ struct dtuple_struct {
UT_LIST_NODE_T(dtuple_t) tuple_list;
/* data tuples can be linked into a
list using this field */
- ulint magic_n;
-};
+#ifdef UNIV_DEBUG
+ ulint magic_n;
#define DATA_TUPLE_MAGIC_N 65478679
+#endif /* UNIV_DEBUG */
+};
/* A slot for a field in a big rec vector */
diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic
index 21f617c7590..946b646ffbf 100644
--- a/innobase/include/data0type.ic
+++ b/innobase/include/data0type.ic
@@ -280,7 +280,7 @@ dtype_get_fixed_size(
case DATA_VARMYSQL:
case DATA_BLOB:
return(0);
- default: ut_a(0);
+ default: ut_error;
}
return(0);
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index 534c9e380b8..688685cff8b 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -493,6 +493,17 @@ dict_table_get_sys_col_no(
/* out: column number */
dict_table_t* table, /* in: table */
ulint sys); /* in: DATA_ROW_ID, ... */
+/************************************************************************
+Checks if a column is in the ordering columns of the clustered index of a
+table. Column prefixes are treated like whole columns. */
+
+ibool
+dict_table_col_in_clustered_key(
+/*============================*/
+ /* out: TRUE if the column, or its prefix, is
+ in the clustered key */
+ dict_table_t* table, /* in: table */
+ ulint n); /* in: column number */
/***********************************************************************
Copies types of columns contained in table to tuple. */
diff --git a/innobase/include/dict0dict.ic b/innobase/include/dict0dict.ic
index c5982c162a7..b70822e331f 100644
--- a/innobase/include/dict0dict.ic
+++ b/innobase/include/dict0dict.ic
@@ -543,8 +543,10 @@ dict_table_check_if_in_cache_low(
ulint table_fold;
ut_ad(table_name);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
+
/* Look for the table name in the hash table */
table_fold = ut_fold_string(table_name);
@@ -566,8 +568,10 @@ dict_table_get_low(
dict_table_t* table;
ut_ad(table_name);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
+
table = dict_table_check_if_in_cache_low(table_name);
if (table == NULL) {
@@ -621,7 +625,9 @@ dict_table_get_on_id_low(
dict_table_t* table;
ulint fold;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
UT_NOT_USED(trx);
/* Look for the table name in the hash table */
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index b18e20a644a..23753df4079 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -198,10 +198,11 @@ struct dict_tree_struct{
the list; if the tree is of the mixed
type, the first index in the list is the
index of the cluster which owns the tree */
+#ifdef UNIV_DEBUG
ulint magic_n;/* magic number */
-};
-
#define DICT_TREE_MAGIC_N 7545676
+#endif /* UNIV_DEBUG */
+};
/* Data structure for an index */
struct dict_index_struct{
@@ -247,7 +248,10 @@ struct dict_index_struct{
ulint stat_n_leaf_pages;
/* approximate number of leaf pages in the
index tree */
+#ifdef UNIV_DEBUG
ulint magic_n;/* magic number */
+#define DICT_INDEX_MAGIC_N 76789786
+#endif /* UNIV_DEBUG */
};
/* Data structure for a foreign key constraint; an example:
@@ -298,9 +302,6 @@ a foreign key constraint is enforced, therefore RESTRICT just means no flag */
#define DICT_FOREIGN_ON_DELETE_NO_ACTION 16
#define DICT_FOREIGN_ON_UPDATE_NO_ACTION 32
-
-#define DICT_INDEX_MAGIC_N 76789786
-
/* Data structure for a database table */
struct dict_table_struct{
dulint id; /* id of the table or cluster */
@@ -419,10 +420,12 @@ struct dict_table_struct{
inited; MySQL gets the init value by executing
SELECT MAX(auto inc column) */
ib_longlong autoinc;/* autoinc counter value to give to the
- next inserted row */
+ next inserted row */
+#ifdef UNIV_DEBUG
ulint magic_n;/* magic number */
-};
#define DICT_TABLE_MAGIC_N 76333786
+#endif /* UNIV_DEBUG */
+};
/* Data structure for a stored procedure */
struct dict_proc_struct{
diff --git a/innobase/include/fut0fut.ic b/innobase/include/fut0fut.ic
index 0f1aa9dd9ae..6a107786376 100644
--- a/innobase/include/fut0fut.ic
+++ b/innobase/include/fut0fut.ic
@@ -30,7 +30,9 @@ fut_get_ptr(
ptr = buf_page_get(space, addr.page, rw_latch, mtr) + addr.boffset;
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(ptr, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
return(ptr);
}
diff --git a/innobase/include/ha0ha.ic b/innobase/include/ha0ha.ic
index 77064cdf9da..5369ca7f273 100644
--- a/innobase/include/ha0ha.ic
+++ b/innobase/include/ha0ha.ic
@@ -81,7 +81,9 @@ ha_search(
{
ha_node_t* node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
+#endif /* UNIV_SYNC_DEBUG */
node = ha_chain_get_first(table, fold);
@@ -111,7 +113,9 @@ ha_search_and_get_data(
{
ha_node_t* node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
+#endif /* UNIV_SYNC_DEBUG */
node = ha_chain_get_first(table, fold);
@@ -170,7 +174,9 @@ ha_search_with_data(
{
ha_node_t* node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
+#endif /* UNIV_SYNC_DEBUG */
node = ha_chain_get_first(table, fold);
@@ -200,7 +206,9 @@ ha_search_and_delete_if_found(
{
ha_node_t* node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
+#endif /* UNIV_SYNC_DEBUG */
node = ha_search_with_data(table, fold, data);
diff --git a/innobase/include/hash0hash.h b/innobase/include/hash0hash.h
index 2e9ab498116..79efe016324 100644
--- a/innobase/include/hash0hash.h
+++ b/innobase/include/hash0hash.h
@@ -53,15 +53,24 @@ hash_calc_hash(
/* out: hashed value */
ulint fold, /* in: folded value */
hash_table_t* table); /* in: hash table */
+/************************************************************************
+Assert that the mutex for the table in a hash operation is owned. */
+#ifdef UNIV_SYNC_DEBUG
+# define HASH_ASSERT_OWNED(TABLE, FOLD) \
+ut_ad(!(TABLE)->mutexes || mutex_own(hash_get_mutex(TABLE, FOLD)));
+#else
+# define HASH_ASSERT_OWNED(TABLE, FOLD)
+#endif
+
/***********************************************************************
Inserts a struct to a hash table. */
#define HASH_INSERT(TYPE, NAME, TABLE, FOLD, DATA)\
-{\
+do {\
hash_cell_t* cell3333;\
TYPE* struct3333;\
\
- ut_ad(!(TABLE)->mutexes || mutex_own(hash_get_mutex(TABLE, FOLD)));\
+ HASH_ASSERT_OWNED(TABLE, FOLD)\
\
(DATA)->NAME = NULL;\
\
@@ -79,17 +88,17 @@ Inserts a struct to a hash table. */
\
struct3333->NAME = DATA;\
}\
-}
+} while (0)
/***********************************************************************
Deletes a struct from a hash table. */
#define HASH_DELETE(TYPE, NAME, TABLE, FOLD, DATA)\
-{\
+do {\
hash_cell_t* cell3333;\
TYPE* struct3333;\
\
- ut_ad(!(TABLE)->mutexes || mutex_own(hash_get_mutex(TABLE, FOLD)));\
+ HASH_ASSERT_OWNED(TABLE, FOLD)\
\
cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
\
@@ -100,13 +109,13 @@ Deletes a struct from a hash table. */
\
while (struct3333->NAME != DATA) {\
\
- ut_a(struct3333)\
+ ut_a(struct3333);\
struct3333 = struct3333->NAME;\
}\
\
struct3333->NAME = DATA->NAME;\
}\
-}
+} while (0)
/***********************************************************************
Gets the first struct in a hash chain, NULL if none. */
@@ -124,7 +133,7 @@ Looks for a struct in a hash table. */
#define HASH_SEARCH(NAME, TABLE, FOLD, DATA, TEST)\
{\
\
- ut_ad(!(TABLE)->mutexes || mutex_own(hash_get_mutex(TABLE, FOLD)));\
+ HASH_ASSERT_OWNED(TABLE, FOLD)\
\
(DATA) = HASH_GET_FIRST(TABLE, hash_calc_hash(FOLD, TABLE));\
\
@@ -160,7 +169,7 @@ the heap. The fold value must be stored in the struct NODE in a field named
'fold'. */
#define HASH_DELETE_AND_COMPACT(TYPE, NAME, TABLE, NODE)\
-{\
+do {\
TYPE* node111;\
TYPE* top_node111;\
hash_cell_t* cell111;\
@@ -211,33 +220,7 @@ the heap. The fold value must be stored in the struct NODE in a field named
/* Free the space occupied by the top node */\
\
mem_heap_free_top(hash_get_heap(TABLE, fold111), sizeof(TYPE));\
-}
-
-/***********************************************************************
-Calculates the number of stored structs in a hash table. */
-
-#define HASH_GET_N_NODES(TYPE, NAME, TABLE, N)\
-{\
- hash_cell_t* cell3333;\
- TYPE* struct3333;\
- ulint i3333;\
-\
- (N) = 0;\
-\
- for (i3333 = 0; i3333 < hash_get_n_cells(TABLE); i3333++) {\
-\
- cell3333 = hash_get_nth_cell(TABLE, i3333);\
-\
- struct3333 = cell3333->node;\
-\
- while (struct3333) {\
-\
- (N) = (N) + 1;\
-\
- struct = HASH_GET_NEXT(NAME, struct3333);\
- }\
- }\
-}
+} while (0)
/****************************************************************
Gets the mutex index for a fold value in a hash table. */
@@ -300,21 +283,6 @@ hash_mutex_exit(
/*============*/
hash_table_t* table, /* in: hash table */
ulint fold); /* in: fold */
-/****************************************************************
-Reserves all the mutexes of a hash table, in an ascending order. */
-
-void
-hash_mutex_enter_all(
-/*=================*/
- hash_table_t* table); /* in: hash table */
-/****************************************************************
-Releases all the mutexes of a hash table. */
-
-void
-hash_mutex_exit_all(
-/*================*/
- hash_table_t* table); /* in: hash table */
-
struct hash_cell_struct{
void* node; /* hash chain node, NULL if none */
@@ -335,10 +303,11 @@ struct hash_table_struct {
memory heaps; there are then n_mutexes many of
these heaps */
mem_heap_t* heap;
+#ifdef UNIV_DEBUG
ulint magic_n;
-};
-
#define HASH_TABLE_MAGIC_N 76561114
+#endif /* UNIV_DEBUG */
+};
#ifndef UNIV_NONINL
#include "hash0hash.ic"
diff --git a/innobase/include/hash0hash.ic b/innobase/include/hash0hash.ic
index 0d713140c13..1b9acfa2f34 100644
--- a/innobase/include/hash0hash.ic
+++ b/innobase/include/hash0hash.ic
@@ -18,6 +18,7 @@ hash_get_nth_cell(
hash_table_t* table, /* in: hash table */
ulint n) /* in: cell index */
{
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(n < table->n_cells);
return(table->array + n);
@@ -32,6 +33,7 @@ hash_get_n_cells(
/* out: number of cells */
hash_table_t* table) /* in: table */
{
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
return(table->n_cells);
}
@@ -45,6 +47,7 @@ hash_calc_hash(
ulint fold, /* in: folded value */
hash_table_t* table) /* in: hash table */
{
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
return(ut_hash_ulint(fold, table->n_cells));
}
@@ -58,6 +61,7 @@ hash_get_mutex_no(
hash_table_t* table, /* in: hash table */
ulint fold) /* in: fold */
{
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
return(ut_2pow_remainder(fold, table->n_mutexes));
}
@@ -71,6 +75,7 @@ hash_get_nth_heap(
hash_table_t* table, /* in: hash table */
ulint i) /* in: index of the heap */
{
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(i < table->n_mutexes);
return(table->heaps[i]);
@@ -88,6 +93,8 @@ hash_get_heap(
{
ulint i;
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
+
if (table->heap) {
return(table->heap);
}
@@ -107,6 +114,7 @@ hash_get_nth_mutex(
hash_table_t* table, /* in: hash table */
ulint i) /* in: index of the mutex */
{
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(i < table->n_mutexes);
return(table->mutexes + i);
diff --git a/innobase/include/ib_odbc.h b/innobase/include/ib_odbc.h
deleted file mode 100644
index 86884b41d39..00000000000
--- a/innobase/include/ib_odbc.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/******************************************************
-Innobase ODBC client library header; this is equivalent to
-the standard sql.h ODBC header file
-
-(c) 1998 Innobase Oy
-
-Created 2/22/1998 Heikki Tuuri
-*******************************************************/
-
-#ifndef ib_odbc_h
-#define ib_odbc_h
-
-typedef unsigned char UCHAR;
-typedef signed char SCHAR;
-typedef long int SDWORD;
-typedef short int SWORD;
-typedef unsigned long int UDWORD;
-typedef unsigned short int UWORD;
-
-typedef void* PTR;
-
-typedef void* HENV;
-typedef void* HDBC;
-typedef void* HSTMT;
-
-typedef signed short RETCODE;
-
-/* RETCODEs */
-#define SQL_NO_DATA_FOUND (-3)
-#define SQL_INVALID_HANDLE (-2)
-#define SQL_ERROR (-1)
-#define SQL_SUCCESS 0
-
-/* Standard SQL datatypes, using ANSI type numbering */
-#define SQL_CHAR 1
-#define SQL_INTEGER 4
-#define SQL_VARCHAR 12
-
-/* C datatype to SQL datatype mapping */
-#define SQL_C_CHAR SQL_CHAR
-#define SQL_C_LONG SQL_INTEGER
-
-/* Special length value */
-#define SQL_NULL_DATA (-1)
-
-#define SQL_PARAM_INPUT 1
-#define SQL_PARAM_OUTPUT 4
-
-/* Null handles */
-#define SQL_NULL_HENV NULL
-#define SQL_NULL_HDBC NULL
-#define SQL_NULL_HSTM NULL
-
-
-/**************************************************************************
-Allocates an SQL environment. */
-
-RETCODE
-SQLAllocEnv(
-/*========*/
- /* out: SQL_SUCCESS */
- HENV* phenv); /* out: pointer to an environment handle */
-/**************************************************************************
-Allocates an SQL connection. */
-
-RETCODE
-SQLAllocConnect(
-/*============*/
- /* out: SQL_SUCCESS */
- HENV henv, /* in: pointer to an environment handle */
- HDBC* phdbc); /* out: pointer to a connection handle */
-/**************************************************************************
-Allocates an SQL statement. */
-
-RETCODE
-SQLAllocStmt(
-/*=========*/
- HDBC hdbc, /* in: SQL connection */
- HSTMT* phstmt); /* out: pointer to a statement handle */
-/**************************************************************************
-Connects to a database server process (establishes a connection and a
-session). */
-
-RETCODE
-SQLConnect(
-/*=======*/
- /* out: SQL_SUCCESS */
- HDBC hdbc, /* in: SQL connection handle */
- UCHAR* szDSN, /* in: data source name (server name) */
- SWORD cbDSN, /* in: data source name length */
- UCHAR* szUID, /* in: user name */
- SWORD cbUID, /* in: user name length */
- UCHAR* szAuthStr, /* in: password */
- SWORD cbAuthStr); /* in: password length */
-/**************************************************************************
-Makes the server to parse and optimize an SQL string. */
-
-RETCODE
-SQLPrepare(
-/*=======*/
- /* out: SQL_SUCCESS */
- HSTMT hstmt, /* in: statement handle */
- UCHAR* szSqlStr, /* in: SQL string */
- SDWORD cbSqlStr); /* in: SQL string length */
-/**************************************************************************
-Binds a parameter in a prepared statement. */
-
-RETCODE
-SQLBindParameter(
-/*=============*/
- /* out: SQL_SUCCESS */
- HSTMT hstmt, /* in: statement handle */
- UWORD ipar, /* in: parameter index, starting from 1 */
- SWORD fParamType, /* in: SQL_PARAM_INPUT or SQL_PARAM_OUTPUT */
- SWORD fCType, /* in: SQL_C_CHAR, ... */
- SWORD fSqlType, /* in: SQL_CHAR, ... */
- UDWORD cbColDef, /* in: precision: ignored */
- SWORD ibScale, /* in: scale: ignored */
- PTR rgbValue, /* in: pointer to a buffer for the data */
- SDWORD cbValueMax, /* in: buffer size */
- SDWORD* pcbValue); /* in: pointer to a buffer for the data
- length or SQL_NULL_DATA */
-/**************************************************************************
-Executes a prepared statement where all parameters have been bound. */
-
-RETCODE
-SQLExecute(
-/*=======*/
- /* out: SQL_SUCCESS or SQL_ERROR */
- HSTMT hstmt); /* in: statement handle */
-/**************************************************************************
-Queries an error message. */
-
-RETCODE
-SQLError(
-/*=====*/
- /* out: SQL_SUCCESS or SQL_NO_DATA_FOUND */
- HENV henv, /* in: SQL_NULL_HENV */
- HDBC hdbc, /* in: SQL_NULL_HDBC */
- HSTMT hstmt, /* in: statement handle */
- UCHAR* szSqlState, /* in/out: SQLSTATE as a null-terminated string,
- (currently, always == "S1000") */
- SDWORD* pfNativeError, /* out: native error code */
- UCHAR* szErrorMsg, /* in/out: buffer for an error message as a
- null-terminated string */
- SWORD cbErrorMsgMax, /* in: buffer size for szErrorMsg */
- SWORD* pcbErrorMsg); /* out: error message length */
-
-#endif
diff --git a/innobase/include/lock0lock.ic b/innobase/include/lock0lock.ic
index 64c43c88d2e..fabc9256401 100644
--- a/innobase/include/lock0lock.ic
+++ b/innobase/include/lock0lock.ic
@@ -64,7 +64,9 @@ lock_clust_rec_some_has_impl(
{
dulint trx_id;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(page_rec_is_user_rec(rec));
diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h
index dc44429d636..2bdc158502f 100644
--- a/innobase/include/log0log.h
+++ b/innobase/include/log0log.h
@@ -18,7 +18,9 @@ typedef struct log_struct log_t;
typedef struct log_group_struct log_group_t;
extern ibool log_do_write;
+#ifdef UNIV_LOG_DEBUG
extern ibool log_debug_writes;
+#endif /* UNIV_LOG_DEBUG */
/* Wait modes for log_write_up_to */
#define LOG_NO_WAIT 91
@@ -719,11 +721,13 @@ struct log_struct{
ulint max_buf_free; /* recommended maximum value of
buf_free, after which the buffer is
flushed */
+#ifdef UNIV_LOG_DEBUG
ulint old_buf_free; /* value of buf free when log was
last time opened; only in the debug
version */
dulint old_lsn; /* value of lsn when log was last time
opened; only in the debug version */
+#endif /* UNIV_LOG_DEBUG */
ibool check_flush_or_checkpoint;
/* this is set to TRUE when there may
be need to flush the log buffer, or
diff --git a/innobase/include/log0log.ic b/innobase/include/log0log.ic
index 7ae7e859032..e273b6a292b 100644
--- a/innobase/include/log0log.ic
+++ b/innobase/include/log0log.ic
@@ -10,6 +10,7 @@ Created 12/9/1995 Heikki Tuuri
#include "mach0data.h"
#include "mtr0mtr.h"
+#ifdef UNIV_LOG_DEBUG
/**********************************************************
Checks by parsing that the catenated log segment for a single mtr is
consistent. */
@@ -21,6 +22,7 @@ log_check_log_recs(
in the log_sys->buf log buffer */
ulint len, /* in: segment length in bytes */
dulint buf_start_lsn); /* in: buffer start lsn */
+#endif /* UNIV_LOG_DEBUG */
/****************************************************************
Gets a log block flush bit. */
@@ -255,7 +257,9 @@ log_block_init(
{
ulint no;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
no = log_block_convert_lsn_to_no(lsn);
@@ -277,7 +281,9 @@ log_block_init_in_old_format(
{
ulint no;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
no = log_block_convert_lsn_to_no(lsn);
@@ -407,7 +413,9 @@ log_get_online_backup_lsn_low(void)
/* out: online_backup_lsn, the caller must
own the log_sys mutex */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(log_sys->online_backup_state);
return(log_sys->online_backup_lsn);
@@ -422,7 +430,9 @@ log_get_online_backup_state_low(void)
/* out: online backup state, the caller must
own the log_sys mutex */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
return(log_sys->online_backup_state);
}
diff --git a/innobase/include/mach0data.h b/innobase/include/mach0data.h
index 006f55d5f1f..f28c9422670 100644
--- a/innobase/include/mach0data.h
+++ b/innobase/include/mach0data.h
@@ -88,25 +88,6 @@ mach_read_from_4(
/*=============*/
/* out: ulint integer */
byte* b); /* in: pointer to four bytes */
-/***********************************************************
-The following function is used to store data from a ulint to memory
-in standard order:
-we store the most significant byte to the lowest address. */
-UNIV_INLINE
-void
-mach_write(
-/*=======*/
- byte* b, /* in: pointer to sizeof(ulint) bytes where to store */
- ulint n); /* in: ulint integer to be stored */
-/************************************************************
-The following function is used to fetch data from memory to a ulint.
-The most significant byte is at the lowest address. */
-UNIV_INLINE
-ulint
-mach_read(
-/*======*/
- /* out: ulint integer */
- byte* b); /* in: pointer to sizeof(ulint) bytes */
/*************************************************************
Writes a ulint in a compressed form. */
UNIV_INLINE
diff --git a/innobase/include/mach0data.ic b/innobase/include/mach0data.ic
index 0934c27d9f4..3ccdcf1dc0a 100644
--- a/innobase/include/mach0data.ic
+++ b/innobase/include/mach0data.ic
@@ -167,44 +167,6 @@ mach_read_from_4(
#endif
}
-/***********************************************************
-The following function is used to store data from a ulint to memory
-in standard order: we store the most significant byte to the lowest
-address. */
-UNIV_INLINE
-void
-mach_write(
-/*=======*/
- byte* b, /* in: pointer to 4 bytes where to store */
- ulint n) /* in: ulint integer to be stored */
-{
- ut_ad(b);
-
- b[0] = (byte)(n >> 24);
- b[1] = (byte)(n >> 16);
- b[2] = (byte)(n >> 8);
- b[3] = (byte)n;
-}
-
-/************************************************************
-The following function is used to fetch data from memory to a ulint.
-The most significant byte is at the lowest address. */
-UNIV_INLINE
-ulint
-mach_read(
-/*======*/
- /* out: ulint integer */
- byte* b) /* in: pointer to 4 bytes */
-{
- ut_ad(b);
-
- return( ((ulint)(b[0]) << 24)
- + ((ulint)(b[1]) << 16)
- + ((ulint)(b[2]) << 8)
- + (ulint)(b[3])
- );
-}
-
/*************************************************************
Writes a ulint in a compressed form where the first byte codes the
length of the stored ulint. We look at the most significant bits of
diff --git a/innobase/include/mem0dbg.ic b/innobase/include/mem0dbg.ic
index 765e23e747e..6efac719760 100644
--- a/innobase/include/mem0dbg.ic
+++ b/innobase/include/mem0dbg.ic
@@ -7,6 +7,7 @@ compilation module but is included in mem0mem.*.
Created 6/8/1994 Heikki Tuuri
*************************************************************************/
+#ifdef UNIV_MEM_DEBUG
extern mutex_t mem_hash_mutex;
extern ulint mem_current_allocated_memory;
@@ -89,3 +90,4 @@ mem_field_trailer_set_check(byte* field, ulint check);
ulint
mem_field_trailer_get_check(byte* field);
+#endif /* UNIV_MEM_DEBUG */
diff --git a/innobase/include/mtr0log.h b/innobase/include/mtr0log.h
index cc42924fe4d..f50c1dfcb6a 100644
--- a/innobase/include/mtr0log.h
+++ b/innobase/include/mtr0log.h
@@ -32,7 +32,6 @@ mlog_write_dulint(
/*==============*/
byte* ptr, /* in: pointer where to write */
dulint val, /* in: value to write */
- byte type, /* in: MLOG_8BYTES */
mtr_t* mtr); /* in: mini-transaction handle */
/************************************************************
Writes a string to a file page buffered in the buffer pool. Writes the
diff --git a/innobase/include/mtr0mtr.h b/innobase/include/mtr0mtr.h
index 8408abf43e4..9cf592f71e1 100644
--- a/innobase/include/mtr0mtr.h
+++ b/innobase/include/mtr0mtr.h
@@ -195,7 +195,6 @@ mtr_read_dulint(
/*===========*/
/* out: value read */
byte* ptr, /* in: pointer from where to read */
- ulint type, /* in: MLOG_8BYTES */
mtr_t* mtr); /* in: mini-transaction handle */
/*************************************************************************
This macro locks an rw-lock in s-mode. */
@@ -296,7 +295,12 @@ struct mtr_memo_slot_struct{
/* Mini-transaction handle and buffer */
struct mtr_struct{
+#ifdef UNIV_DEBUG
ulint state; /* MTR_ACTIVE, MTR_COMMITTING, MTR_COMMITTED */
+#define MTR_ACTIVE 12231
+#define MTR_COMMITTING 56456
+#define MTR_COMMITTED 34676
+#endif /* UNIV_DEBUG */
dyn_array_t memo; /* memo stack for locks etc. */
dyn_array_t log; /* mini-transaction log */
ibool modifications;
@@ -311,15 +315,12 @@ struct mtr_struct{
this mtr */
dulint end_lsn;/* end lsn of the possible log entry for
this mtr */
+#ifdef UNIV_DEBUG
ulint magic_n;
-};
-
#define MTR_MAGIC_N 54551
+#endif /* UNIV_DEBUG */
+};
-#define MTR_ACTIVE 12231
-#define MTR_COMMITTING 56456
-#define MTR_COMMITTED 34676
-
#ifndef UNIV_NONINL
#include "mtr0mtr.ic"
#endif
diff --git a/innobase/include/odbc0odbc.h b/innobase/include/odbc0odbc.h
deleted file mode 100644
index 7f842b54b27..00000000000
--- a/innobase/include/odbc0odbc.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/******************************************************
-Innobase ODBC client library additional header
-
-(c) 1998 Innobase Oy
-
-Created 2/22/1998 Heikki Tuuri
-*******************************************************/
-
-#ifndef odbc0odbc_h
-#define odbc0odbc_h
-
-#include "ib_odbc.h"
-
-/* Datagram size in communications */
-#define ODBC_DATAGRAM_SIZE 8192
-
-/* Communication address maximum length in bytes */
-#define ODBC_ADDRESS_SIZE COM_MAX_ADDR_LEN
-
-#endif
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index 5f2d6e3ed21..813e6e72e65 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -20,6 +20,9 @@ extern ibool os_do_not_call_flush_at_each_write;
extern ibool os_has_said_disk_full;
extern ibool os_aio_print_debug;
+extern ulint os_file_n_pending_preads;
+extern ulint os_file_n_pending_pwrites;
+
#ifdef __WIN__
/* We define always WIN_ASYNC_IO, and check at run-time whether
@@ -60,6 +63,7 @@ log. */
#define OS_FILE_CREATE 52
#define OS_FILE_OVERWRITE 53
#define OS_FILE_OPEN_RAW 54
+#define OS_FILE_CREATE_PATH 55
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
@@ -228,7 +232,9 @@ os_file_create_simple(
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
(if does not exist, error), or OS_FILE_CREATE if a new
- file is created (if exists, error) */
+ file is created (if exists, error), or
+ OS_FILE_CREATE_PATH if new file (if exists, error) and
+ subdirectories along its path are created (if needed)*/
ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */
ibool* success);/* out: TRUE if succeed, FALSE if error */
/********************************************************************
@@ -421,6 +427,59 @@ os_file_write(
ulint offset_high,/* in: most significant 32 bits of
offset */
ulint n); /* in: number of bytes to write */
+/***********************************************************************
+Check the existence and type of the given file. */
+
+ibool
+os_file_status(
+/*===========*/
+ /* out: TRUE if call succeeded */
+ char * path, /* in: pathname of the file */
+ ibool * exists, /* out: TRUE if file exists */
+ os_file_type_t* type); /* out: type of the file (if it exists) */
+/********************************************************************
+The function os_file_dirname returns a directory component of a
+null-terminated pathname string. In the usual case, dirname returns
+the string up to, but not including, the final '/', and basename
+is the component following the final '/'. Trailing '/' charac­
+ters are not counted as part of the pathname.
+
+If path does not contain a slash, dirname returns the string ".".
+
+Concatenating the string returned by dirname, a "/", and the basename
+yields a complete pathname.
+
+The return value is a copy of the directory component of the pathname.
+The copy is allocated from heap. It is the caller responsibility
+to free it after it is no longer needed.
+
+The following list of examples (taken from SUSv2) shows the strings
+returned by dirname and basename for different paths:
+
+ path dirname basename
+ "/usr/lib" "/usr" "lib"
+ "/usr/" "/" "usr"
+ "usr" "." "usr"
+ "/" "/" "/"
+ "." "." "."
+ ".." "." ".."
+*/
+
+char*
+os_file_dirname(
+/*============*/
+ /* out, own: directory component of the
+ pathname */
+ char* path); /* in: pathname */
+/********************************************************************
+Creates all missing subdirectories along the given path. */
+
+ibool
+os_file_create_subdirs_if_needed(
+/*=============================*/
+ /* out: TRUE if call succeeded
+ FALSE otherwise */
+ char* path); /* in: path name */
/****************************************************************************
Initializes the asynchronous io system. Creates separate aio array for
non-ibuf read and write, a third aio array for the ibuf i/o, with just one
diff --git a/innobase/include/page0cur.h b/innobase/include/page0cur.h
index c3f0decdb4b..c85669ed4df 100644
--- a/innobase/include/page0cur.h
+++ b/innobase/include/page0cur.h
@@ -32,8 +32,11 @@ Created 10/4/1994 Heikki Tuuri
which extend it */
#define PAGE_CUR_DBG 6
-
+#ifdef PAGE_CUR_ADAPT
+# ifdef UNIV_SEARCH_PERF_STAT
extern ulint page_cur_short_succ;
+# endif /* UNIV_SEARCH_PERF_STAT */
+#endif /* PAGE_CUR_ADAPT */
/*************************************************************
Gets pointer to the page frame where the cursor is positioned. */
diff --git a/innobase/include/pars0pars.h b/innobase/include/pars0pars.h
index e08b071e246..8ff226ebbd0 100644
--- a/innobase/include/pars0pars.h
+++ b/innobase/include/pars0pars.h
@@ -21,7 +21,9 @@ extern int yydebug;
/* If the following is set TRUE, the lexer will print the SQL string
as it tokenizes it */
+#ifdef UNIV_SQL_DEBUG
extern ibool pars_print_lexed;
+#endif /* UNIV_SQL_DEBUG */
/* Global variable used while parsing a single procedure or query : the code is
NOT re-entrant */
@@ -390,41 +392,18 @@ pars_procedure_definition(
table */
sym_node_t* param_list, /* in: parameter declaration list */
que_node_t* stat_list); /* in: statement list */
-/*****************************************************************
-Reads stored procedure input parameter values from a buffer. */
-
-void
-pars_proc_read_input_params_from_buf(
-/*=================================*/
- que_t* graph, /* in: query graph which contains a stored procedure */
- byte* buf); /* in: buffer */
-/*****************************************************************
-Writes stored procedure output parameter values to a buffer. */
-ulint
-pars_proc_write_output_params_to_buf(
-/*=================================*/
- byte* buf, /* in: buffer which must be big enough */
- que_t* graph); /* in: query graph which contains a stored procedure */
/*****************************************************************
Parses a stored procedure call, when this is not within another stored
-procedure, that is, the client issues a procedure call directly. */
+procedure, that is, the client issues a procedure call directly.
+In MySQL/InnoDB, stored InnoDB procedures are invoked via the
+parsed procedure tree, not via InnoDB SQL, so this function is not used. */
que_fork_t*
pars_stored_procedure_call(
/*=======================*/
/* out: query graph */
sym_node_t* sym_node); /* in: stored procedure name */
-/*****************************************************************
-Writes info about query parameter markers (denoted with '?' in ODBC) into a
-buffer. */
-
-ulint
-pars_write_query_param_info(
-/*========================*/
- /* out: number of bytes used for info in buf */
- byte* buf, /* in: buffer which must be big enough */
- que_fork_t* graph); /* in: parsed query graph */
/**********************************************************************
Completes a query graph by adding query thread and fork nodes
above it and prepares the graph for running. The fork created is of
diff --git a/innobase/include/que0que.h b/innobase/include/que0que.h
index a3ed18e2b14..bcd7aed7e88 100644
--- a/innobase/include/que0que.h
+++ b/innobase/include/que0que.h
@@ -216,9 +216,7 @@ que_fork_start_command(
QUE_THR_RUNNING state, or NULL; the query
thread should be executed by que_run_threads
by the caller */
- que_fork_t* fork, /* in: a query fork */
- ulint command,/* in: command SESS_COMM_FETCH_NEXT, ... */
- ulint param); /* in: possible parameter to the command */
+ que_fork_t* fork); /* in: a query fork */
/***************************************************************************
Gets the trx of a query thread. */
UNIV_INLINE
@@ -309,22 +307,6 @@ que_thr_peek_stop(
mutex reserved is necessary before deciding
the actual stopping */
que_thr_t* thr); /* in: query thread */
-/***************************************************************************
-Returns TRUE if the query graph is for a SELECT statement. */
-UNIV_INLINE
-ibool
-que_graph_is_select(
-/*================*/
- /* out: TRUE if a select */
- que_t* graph); /* in: graph */
-/**************************************************************************
-Prints info of an SQL query graph node. */
-
-void
-que_node_print_info(
-/*================*/
- que_node_t* node); /* in: query graph node */
-
/* Query graph query thread node: the fields are protected by the kernel
mutex with the exceptions named below */
@@ -388,11 +370,6 @@ struct que_fork_struct{
sym_tab_t* sym_tab; /* symbol table of the query,
generated by the parser, or NULL
if the graph was created 'by hand' */
- ulint id; /* id of this query graph */
- ulint command; /* command currently executed in the
- graph */
- ulint param; /* possible command parameter */
-
/* The following cur_... fields are relevant only in a select graph */
ulint cur_end; /* QUE_CUR_NOT_DEFINED, QUE_CUR_START,
diff --git a/innobase/include/que0que.ic b/innobase/include/que0que.ic
index ae4ed10560f..a63922f8c80 100644
--- a/innobase/include/que0que.ic
+++ b/innobase/include/que0que.ic
@@ -238,21 +238,3 @@ que_thr_peek_stop(
return(FALSE);
}
-
-/***************************************************************************
-Returns TRUE if the query graph is for a SELECT statement. */
-UNIV_INLINE
-ibool
-que_graph_is_select(
-/*================*/
- /* out: TRUE if a select */
- que_t* graph) /* in: graph */
-{
- if (graph->fork_type == QUE_FORK_SELECT_SCROLL
- || graph->fork_type == QUE_FORK_SELECT_NON_SCROLL) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
diff --git a/innobase/include/row0ins.h b/innobase/include/row0ins.h
index a5b4b74e7fc..f3f0b7e8eca 100644
--- a/innobase/include/row0ins.h
+++ b/innobase/include/row0ins.h
@@ -145,10 +145,11 @@ struct ins_node_struct{
entry_list and sys fields are stored here;
if this is NULL, entry list should be created
and buffers for sys fields in row allocated */
+#ifdef UNIV_DEBUG
ulint magic_n;
-};
-
#define INS_NODE_MAGIC_N 15849075
+#endif /* UNIV_DEBUG */
+};
/* Insert node types */
#define INS_SEARCHED 0 /* INSERT INTO ... SELECT ... */
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index fade3709631..32a0c8b5d75 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -510,13 +510,15 @@ struct row_prebuilt_struct {
byte* ins_upd_rec_buff;/* buffer for storing data converted
to the Innobase format from the MySQL
format */
- ibool hint_no_need_to_fetch_extra_cols;
- /* normally this is TRUE, but
- MySQL will set this to FALSE
- if we might be required to fetch also
- other columns than mentioned in the
- query: the clustered index column(s),
- or an auto-increment column*/
+ ulint hint_need_to_fetch_extra_cols;
+ /* normally this is set to 0; if this
+ is set to ROW_RETRIEVE_PRIMARY_KEY,
+ then we should at least retrieve all
+ columns in the primary key; if this
+ is set to ROW_RETRIEVE_ALL_COLS, then
+ we must retrieve all columns in the
+ key (if read_just_key == 1), or all
+ columns in the table */
upd_node_t* upd_node; /* Innobase SQL update node used
to perform updates and deletes */
que_fork_t* ins_graph; /* Innobase SQL query graph used
@@ -572,6 +574,11 @@ struct row_prebuilt_struct {
#define ROW_MYSQL_DUMMY_TEMPLATE 3 /* dummy template used in
row_scan_and_check_index */
+/* Values for hint_need_to_fetch_extra_cols */
+#define ROW_RETRIEVE_PRIMARY_KEY 1
+#define ROW_RETRIEVE_ALL_COLS 2
+
+
#ifndef UNIV_NONINL
#include "row0mysql.ic"
#endif
diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h
index f5e0a88231f..687e90deee5 100644
--- a/innobase/include/row0upd.h
+++ b/innobase/include/row0upd.h
@@ -384,10 +384,11 @@ struct upd_node_struct{
sym_node_t* table_sym;/* table node in symbol table */
que_node_t* col_assign_list;
/* column assignment list */
+#ifdef UNIV_DEBUG
ulint magic_n;
-};
-
#define UPD_NODE_MAGIC_N 1579975
+#endif /* UNIV_DEBUG */
+};
/* Node execution states */
#define UPD_NODE_SET_IX_LOCK 1 /* execution came to the node from
diff --git a/innobase/include/row0upd.ic b/innobase/include/row0upd.ic
index 1878431d1a4..6b9deeac5e3 100644
--- a/innobase/include/row0upd.ic
+++ b/innobase/include/row0upd.ic
@@ -107,8 +107,10 @@ row_upd_rec_sys_fields(
dulint roll_ptr)/* in: roll ptr of the undo log record */
{
ut_ad(index->type & DICT_CLUSTERED);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!buf_block_align(rec)->is_hashed
|| rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
row_set_rec_trx_id(rec, index, trx->id);
row_set_rec_roll_ptr(rec, index, roll_ptr);
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 23c30554f08..8aac71de2a9 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -13,7 +13,6 @@ Created 10/10/1995 Heikki Tuuri
#include "univ.i"
#include "sync0sync.h"
#include "os0sync.h"
-#include "com0com.h"
#include "que0types.h"
#include "trx0types.h"
@@ -405,9 +404,6 @@ struct srv_sys_struct{
os_event_t operational; /* created threads must wait for the
server to become operational by
waiting for this event */
- com_endpoint_t* endpoint; /* the communication endpoint of the
- server */
-
srv_table_t* threads; /* server thread table */
UT_LIST_BASE_NODE_T(que_thr_t)
tasks; /* task queue */
diff --git a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h
index 5aa3dcdffc3..d71691b4353 100644
--- a/innobase/include/sync0rw.h
+++ b/innobase/include/sync0rw.h
@@ -25,13 +25,16 @@ smaller than 30 and the order of the numerical values like below! */
#define RW_NO_LATCH 3
typedef struct rw_lock_struct rw_lock_t;
+#ifdef UNIV_SYNC_DEBUG
typedef struct rw_lock_debug_struct rw_lock_debug_t;
+#endif /* UNIV_SYNC_DEBUG */
typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t;
extern rw_lock_list_t rw_lock_list;
extern mutex_t rw_lock_list_mutex;
+#ifdef UNIV_SYNC_DEBUG
/* The global mutex which protects debug info lists of all rw-locks.
To modify the debug info list of an rw-lock, this mutex has to be
@@ -42,6 +45,7 @@ extern os_event_t rw_lock_debug_event; /* If deadlock detection does
may wait for this event */
extern ibool rw_lock_debug_waiters; /* This is set to TRUE, if
there may be waiters for the event */
+#endif /* UNIV_SYNC_DEBUG */
extern ulint rw_s_system_call_count;
extern ulint rw_s_spin_wait_count;
@@ -327,6 +331,7 @@ ulint
rw_lock_get_reader_count(
/*=====================*/
rw_lock_t* lock);
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Checks if the thread has locked the rw-lock in the specified mode, with
the pass value == 0. */
@@ -337,6 +342,7 @@ rw_lock_own(
rw_lock_t* lock, /* in: rw-lock */
ulint lock_type); /* in: lock type: RW_LOCK_SHARED,
RW_LOCK_EX */
+#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Checks if somebody has locked the rw-lock in the specified mode. */
@@ -346,6 +352,7 @@ rw_lock_is_locked(
rw_lock_t* lock, /* in: rw-lock */
ulint lock_type); /* in: lock type: RW_LOCK_SHARED,
RW_LOCK_EX */
+#ifdef UNIV_SYNC_DEBUG
/*******************************************************************
Prints debug info of an rw-lock. */
@@ -392,6 +399,7 @@ void
rw_lock_debug_print(
/*================*/
rw_lock_debug_t* info); /* in: debug struct */
+#endif /* UNIV_SYNC_DEBUG */
/* NOTE! The structure appears here only for the compiler to know its size.
Do not use its fields directly! The structure used in the spin lock
@@ -434,10 +442,12 @@ struct rw_lock_struct {
UT_LIST_NODE_T(rw_lock_t) list;
/* All allocated rw locks are put into a
list */
+#ifdef UNIV_SYNC_DEBUG
UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list;
/* In the debug version: pointer to the debug
info list of the lock */
- ulint level; /* Debug version: level in the global latching
+#endif /* UNIV_SYNC_DEBUG */
+ ulint level; /* Level in the global latching
order; default SYNC_LEVEL_NONE */
char* cfile_name; /* File name where lock created */
ulint cline; /* Line where created */
@@ -450,6 +460,7 @@ struct rw_lock_struct {
#define RW_LOCK_MAGIC_N 22643
+#ifdef UNIV_SYNC_DEBUG
/* The structure for storing debug info of an rw-lock */
struct rw_lock_debug_struct {
@@ -464,6 +475,7 @@ struct rw_lock_debug_struct {
/* Debug structs are linked in a two-way
list */
};
+#endif /* UNIV_SYNC_DEBUG */
#ifndef UNIV_NONINL
#include "sync0rw.ic"
diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
index caf6f5f1de4..8fc93f4a9da 100644
--- a/innobase/include/sync0rw.ic
+++ b/innobase/include/sync0rw.ic
@@ -20,6 +20,7 @@ rw_lock_s_lock_spin(
be passed to another thread to unlock */
char* file_name,/* in: file name where lock requested */
ulint line); /* in: line where requested */
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Inserts the debug information for an rw-lock. */
@@ -40,7 +41,7 @@ rw_lock_remove_debug_info(
rw_lock_t* lock, /* in: rw-lock */
ulint pass, /* in: pass value */
ulint lock_type); /* in: lock type */
-
+#endif /* UNIV_SYNC_DEBUG */
/************************************************************************
Accessor functions for rw lock. */
@@ -132,8 +133,9 @@ rw_lock_s_lock_low(
char* file_name, /* in: file name where lock requested */
ulint line) /* in: line where requested */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
-
+#endif /* UNIV_SYNC_DEBUG */
/* Check if the writer field is free */
if (lock->writer == RW_LOCK_NOT_LOCKED) {
@@ -144,7 +146,6 @@ rw_lock_s_lock_low(
rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name,
line);
#endif
-
lock->last_s_file_name = file_name;
lock->last_s_line = line;
@@ -236,7 +237,9 @@ rw_lock_s_lock_func(
the threads which have s-locked a latch. This would use some CPU
time. */
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
+#endif /* UNIV_SYNC_DEBUG */
mutex_enter(rw_lock_get_mutex(lock));
diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h
index f83f8cbe712..3a7203bbb56 100644
--- a/innobase/include/sync0sync.h
+++ b/innobase/include/sync0sync.h
@@ -185,6 +185,7 @@ sync_thread_levels_empty_gen(
allowed to be owned by the thread,
also purge_is_running mutex is
allowed */
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Checks that the current thread owns the mutex. Works only
in the debug version. */
@@ -217,6 +218,7 @@ Prints debug info of currently reserved mutexes. */
void
mutex_list_print_info(void);
/*========================*/
+#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
NOT to be used outside this module except in debugging! Gets the value
of the lock word. */
@@ -225,6 +227,7 @@ ulint
mutex_get_lock_word(
/*================*/
mutex_t* mutex); /* in: mutex */
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
NOT to be used outside this module except in debugging! Gets the waiters
field in a mutex. */
@@ -234,6 +237,7 @@ mutex_get_waiters(
/*==============*/
/* out: value to set */
mutex_t* mutex); /* in: mutex */
+#endif /* UNIV_SYNC_DEBUG */
/*
LATCHING ORDER WITHIN THE DATABASE
@@ -442,13 +446,13 @@ struct mutex_struct {
Otherwise, this is 0. */
UT_LIST_NODE_T(mutex_t) list; /* All allocated mutexes are put into
a list. Pointers to the next and prev. */
+#ifdef UNIV_SYNC_DEBUG
+ const char* file_name; /* File where the mutex was locked */
+ ulint line; /* Line where the mutex was locked */
os_thread_id_t thread_id; /* Debug version: The thread id of the
thread which locked the mutex. */
- char* file_name; /* Debug version: File name where the mutex
- was locked */
- ulint line; /* Debug version: Line where the mutex was
- locked */
- ulint level; /* Debug version: level in the global latching
+#endif /* UNIV_SYNC_DEBUG */
+ ulint level; /* Level in the global latching
order; default SYNC_LEVEL_NONE */
char* cfile_name; /* File name where mutex created */
ulint cline; /* Line where created */
diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic
index 816b44a5bd3..758c8524f66 100644
--- a/innobase/include/sync0sync.ic
+++ b/innobase/include/sync0sync.ic
@@ -25,6 +25,7 @@ mutex_spin_wait(
mutex_t* mutex, /* in: pointer to mutex */
char* file_name,/* in: file name where mutex requested */
ulint line); /* in: line where requested */
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Sets the debug information for a reserved mutex. */
@@ -34,6 +35,7 @@ mutex_set_debug_info(
mutex_t* mutex, /* in: mutex */
char* file_name, /* in: file where requested */
ulint line); /* in: line where requested */
+#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Releases the threads waiting in the primary wait array for this mutex. */
@@ -200,9 +202,9 @@ mutex_exit(
/*=======*/
mutex_t* mutex) /* in: pointer to mutex */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(mutex));
-#ifdef UNIV_SYNC_DEBUG
mutex->thread_id = ULINT_UNDEFINED;
sync_thread_reset_level(mutex);
@@ -249,14 +251,9 @@ mutex_enter_func(
the atomic test_and_set; we could peek, and possibly save time. */
if (!mutex_test_and_set(mutex)) {
-
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
-
- mutex->file_name = file_name;
- mutex->line = line;
-
return; /* Succeeded! */
}
diff --git a/innobase/include/trx0rseg.ic b/innobase/include/trx0rseg.ic
index 6b242b66c09..35e927f5e79 100644
--- a/innobase/include/trx0rseg.ic
+++ b/innobase/include/trx0rseg.ic
@@ -24,7 +24,9 @@ trx_rsegf_get(
header = TRX_RSEG + buf_page_get(space, page_no, RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(header, SYNC_RSEG_HEADER);
+#endif /* UNIV_SYNC_DEBUG */
return(header);
}
@@ -45,7 +47,9 @@ trx_rsegf_get_new(
header = TRX_RSEG + buf_page_get(space, page_no, RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(header, SYNC_RSEG_HEADER_NEW);
+#endif /* UNIV_SYNC_DEBUG */
return(header);
}
@@ -64,7 +68,7 @@ trx_rsegf_get_nth_undo(
if (n >= TRX_RSEG_N_SLOTS) {
fprintf(stderr,
"InnoDB: Error: trying to get slot %lu of rseg\n", (unsigned long) n);
- ut_a(0);
+ ut_error;
}
return(mtr_read_ulint(rsegf + TRX_RSEG_UNDO_SLOTS +
@@ -85,7 +89,7 @@ trx_rsegf_set_nth_undo(
if (n >= TRX_RSEG_N_SLOTS) {
fprintf(stderr,
"InnoDB: Error: trying to set slot %lu of rseg\n", (unsigned long) n);
- ut_a(0);
+ ut_error;
}
mlog_write_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + n * TRX_RSEG_SLOT_SIZE,
diff --git a/innobase/include/trx0sys.ic b/innobase/include/trx0sys.ic
index 343e6d7c2fa..8f455e554ea 100644
--- a/innobase/include/trx0sys.ic
+++ b/innobase/include/trx0sys.ic
@@ -60,7 +60,9 @@ trx_sys_get_nth_rseg(
trx_sys_t* sys, /* in: trx system */
ulint n) /* in: index of slot */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(n < TRX_SYS_N_RSEGS);
return(sys->rseg_array[n]);
@@ -98,7 +100,9 @@ trx_sysf_get(
header = TRX_SYS + buf_page_get(TRX_SYS_SPACE, TRX_SYS_PAGE_NO,
RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(header, SYNC_TRX_SYS_HEADER);
+#endif /* UNIV_SYNC_DEBUG */
return(header);
}
@@ -115,7 +119,9 @@ trx_sysf_rseg_get_space(
ulint i, /* in: slot index == rseg id */
mtr_t* mtr) /* in: mtr */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(sys_header);
ut_ad(i < TRX_SYS_N_RSEGS);
@@ -138,7 +144,9 @@ trx_sysf_rseg_get_page_no(
mtr_t* mtr) /* in: mtr */
{
ut_ad(sys_header);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(i < TRX_SYS_N_RSEGS);
return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS
@@ -158,7 +166,9 @@ trx_sysf_rseg_set_space(
ulint space, /* in: space id */
mtr_t* mtr) /* in: mtr */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(sys_header);
ut_ad(i < TRX_SYS_N_RSEGS);
@@ -182,7 +192,9 @@ trx_sysf_rseg_set_page_no(
slot is reset to unused */
mtr_t* mtr) /* in: mtr */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(sys_header);
ut_ad(i < TRX_SYS_N_RSEGS);
@@ -236,7 +248,9 @@ trx_get_on_id(
{
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
@@ -266,7 +280,9 @@ trx_list_get_min_trx_id(void)
{
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
trx = UT_LIST_GET_LAST(trx_sys->trx_list);
@@ -289,7 +305,9 @@ trx_is_active(
{
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (ut_dulint_cmp(trx_id, trx_list_get_min_trx_id()) < 0) {
@@ -325,7 +343,9 @@ trx_sys_get_new_trx_id(void)
{
dulint id;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
/* VERY important: after the database is started, max_trx_id value is
divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if
@@ -355,7 +375,9 @@ trx_sys_get_new_trx_no(void)
/*========================*/
/* out: new, allocated trx number */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
return(trx_sys_get_new_trx_id());
}
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 6b08b674db8..d9b91ee62dc 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -203,13 +203,9 @@ trx_sig_send(
ulint type, /* in: signal type */
ulint sender, /* in: TRX_SIG_SELF or
TRX_SIG_OTHER_SESS */
- ibool reply, /* in: TRUE if the sender of the signal
- wants reply after the operation induced
- by the signal is completed; if type
- is TRX_SIG_END_WAIT, this must be
- FALSE */
que_thr_t* receiver_thr, /* in: query thread which wants the
- reply, or NULL */
+ reply, or NULL; if type is
+ TRX_SIG_END_WAIT, this must be NULL */
trx_savept_t* savept, /* in: possible rollback savepoint, or
NULL */
que_thr_t** next_thr); /* in/out: next query thread to run;
@@ -225,7 +221,6 @@ been handled. */
void
trx_sig_reply(
/*==========*/
- trx_t* trx, /* in: trx handle */
trx_sig_t* sig, /* in: signal */
que_thr_t** next_thr); /* in/out: next query thread to run;
if the value which is passed in is
@@ -297,15 +292,9 @@ struct trx_sig_struct{
TRX_SIG_BEING_HANDLED */
ulint sender; /* TRX_SIG_SELF or
TRX_SIG_OTHER_SESS */
- ibool reply; /* TRUE if the sender of the signal
+ que_thr_t* receiver; /* non-NULL if the sender of the signal
wants reply after the operation induced
- by the signal is completed; if this
- field is TRUE and the receiver field
- below is NULL, then a SUCCESS message
- is sent to the client of the session
- to which this trx belongs */
- que_thr_t* receiver; /* query thread which wants the reply,
- or NULL */
+ by the signal is completed */
trx_savept_t savept; /* possible rollback savepoint */
UT_LIST_NODE_T(trx_sig_t)
signals; /* queue of pending signals to the
diff --git a/innobase/include/trx0undo.h b/innobase/include/trx0undo.h
index 7f0378c68d3..20002076cc3 100644
--- a/innobase/include/trx0undo.h
+++ b/innobase/include/trx0undo.h
@@ -251,20 +251,6 @@ trx_undo_update_cleanup(
page_t* undo_page, /* in: update undo log header page,
x-latched */
mtr_t* mtr); /* in: mtr */
-/**************************************************************************
-Discards an undo log and puts the segment to the list of cached update undo
-log segments. This optimized function is called if there is no need to
-keep the update undo log because there exist no read views and the transaction
-made no delete markings, which would make purge necessary. We restrict this
-to undo logs of size 1 to make things simpler. */
-
-dulint
-trx_undo_update_cleanup_by_discard(
-/*===============================*/
- /* out: log sequence number at which mtr is
- committed */
- trx_t* trx, /* in: trx owning the update undo log */
- mtr_t* mtr); /* in: mtr */
/**********************************************************************
Frees or caches an insert undo log after a transaction commit or rollback.
Knowledge of inserts is not needed after a commit or rollback, therefore
diff --git a/innobase/include/trx0undo.ic b/innobase/include/trx0undo.ic
index bedbc02b00b..a04b234b495 100644
--- a/innobase/include/trx0undo.ic
+++ b/innobase/include/trx0undo.ic
@@ -126,7 +126,9 @@ trx_undo_page_get(
page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TRX_UNDO_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
return(page);
}
@@ -146,7 +148,9 @@ trx_undo_page_get_s_latched(
page = buf_page_get(space, page_no, RW_S_LATCH, mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TRX_UNDO_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
return(page);
}
diff --git a/innobase/include/usr0sess.h b/innobase/include/usr0sess.h
index e277d801672..c7bcfb20fed 100644
--- a/innobase/include/usr0sess.h
+++ b/innobase/include/usr0sess.h
@@ -11,7 +11,6 @@ Created 6/25/1996 Heikki Tuuri
#include "univ.i"
#include "ut0byte.h"
-#include "hash0hash.h"
#include "trx0types.h"
#include "srv0srv.h"
#include "trx0types.h"
@@ -19,52 +18,14 @@ Created 6/25/1996 Heikki Tuuri
#include "que0types.h"
#include "data0data.h"
#include "rem0rec.h"
-#include "com0com.h"
-/* The session system global data structure */
-extern sess_sys_t* sess_sys;
-
-/*************************************************************************
-Sets the session id in a client message. */
-
-void
-sess_cli_msg_set_sess(
-/*==================*/
- byte* str, /* in/out: message string */
- dulint sess_id);/* in: session id */
-/***************************************************************************
-Sets the message type of a message from the client. */
-UNIV_INLINE
-void
-sess_cli_msg_set_type(
-/*==================*/
- byte* str, /* in: message string */
- ulint type); /* in: message type */
-/***************************************************************************
-Gets the message type of a message from the server. */
-UNIV_INLINE
-ulint
-sess_srv_msg_get_type(
-/*==================*/
- /* out: message type */
- byte* str); /* in: message string */
-/***************************************************************************
-Creates a session sytem at database start. */
-
-void
-sess_sys_init_at_db_start(void);
-/*===========================*/
/*************************************************************************
Opens a session. */
sess_t*
-sess_open(
-/*======*/
+sess_open(void);
+/*============*/
/* out, own: session object */
- com_endpoint_t* endpoint, /* in: communication endpoint used
- for communicating with the client */
- byte* addr_buf, /* in: client address */
- ulint addr_len); /* in: client address length */
/*************************************************************************
Closes a session, freeing the memory occupied by it, if it is in a state
where it should be closed. */
@@ -74,200 +35,25 @@ sess_try_close(
/*===========*/
/* out: TRUE if closed */
sess_t* sess); /* in, own: session object */
-/*************************************************************************
-Initializes the first fields of a message to client. */
-
-void
-sess_srv_msg_init(
-/*==============*/
- sess_t* sess, /* in: session object */
- byte* buf, /* in: message buffer, must be at least of size
- SESS_SRV_MSG_DATA */
- ulint type); /* in: message type */
-/*************************************************************************
-Sends a simple message to client. */
-
-void
-sess_srv_msg_send_simple(
-/*=====================*/
- sess_t* sess, /* in: session object */
- ulint type, /* in: message type */
- ulint rel_kernel); /* in: SESS_RELEASE_KERNEL or
- SESS_NOT_RELEASE_KERNEL */
-/***************************************************************************
-When a command has been completed, this function sends the message about it
-to the client. */
-
-void
-sess_command_completed_message(
-/*===========================*/
- sess_t* sess, /* in: session */
- byte* msg, /* in: message buffer */
- ulint len); /* in: message data length */
-
/* The session handle. All fields are protected by the kernel mutex */
struct sess_struct{
- dulint id; /* session id */
- dulint usr_id; /* user id */
- hash_node_t hash; /* hash chain node */
- ulint refer_count; /* reference count to the session
- object: when this drops to zero
- and the session has no query graphs
- left, discarding the session object
- is allowed */
- dulint error_count; /* if this counter has increased while
- a thread is parsing an SQL command,
- its graph should be discarded */
- ibool disconnecting; /* TRUE if the session is to be
- disconnected when its reference
- count drops to 0 */
ulint state; /* state of the session */
- dulint msgs_sent; /* count of messages sent to the
- client */
- dulint msgs_recv; /* count of messages received from the
- client */
- ibool client_waits; /* when the session receives a message
- from the client, this set to TRUE, and
- when the session sends a message to
- the client this is set to FALSE */
trx_t* trx; /* transaction object permanently
assigned for the session: the
transaction instance designated by the
trx id changes, but the memory
structure is preserved */
- ulint next_graph_id; /* next query graph id to assign */
UT_LIST_BASE_NODE_T(que_t)
graphs; /* query graphs belonging to this
session */
- /*------------------------------*/
- ulint err_no; /* latest error number, 0 if none */
- char* err_str; /* latest error string */
- ulint err_len; /* error string length */
- /*------------------------------*/
- com_endpoint_t* endpoint; /* server communications endpoint used
- to communicate with the client */
- char* addr_buf; /* client address string */
- ulint addr_len; /* client address string length */
- /*------------------------------*/
- byte* big_msg; /* if the client sends a message which
- does not fit in a single packet,
- it is assembled in this buffer; if
- this field is not NULL, it is assumed
- that the message should be catenated
- here */
- ulint big_msg_size; /* size of the big message buffer */
- ulint big_msg_len; /* length of data in the big message
- buffer */
-};
-
-/* The session system; this is protected by the kernel mutex */
-struct sess_sys_struct{
- ulint state; /* state of the system:
- SESS_SYS_RUNNING or
- SESS_SYS_SHUTTING_DOWN */
- sess_t* shutdown_req; /* if shutdown was requested by some
- session, confirmation of shutdown
- completion should be sent to this
- session */
- dulint free_sess_id; /* first unused session id */
- hash_table_t* hash; /* hash table of the sessions */
};
-
-/*---------------------------------------------------*/
-/* The format of an incoming message from a client */
-#define SESS_CLI_MSG_CHECKSUM 0 /* the checksum should be the first
- field in the message */
-#define SESS_CLI_MSG_SESS_ID 4 /* this is set to 0 if the client
- wants to connect and establish
- a new session */
-#define SESS_CLI_MSG_SESS_ID_CHECK 12 /* checksum of the sess id field */
-#define SESS_CLI_MSG_TYPE 16
-#define SESS_CLI_MSG_NO 20
-#define SESS_CLI_MSG_CONTINUE 28 /* 0, or SESS_MSG_FIRST_PART
- SESS_MSG_MIDDLE_PART, or
- SESS_MSG_LAST_PART */
-#define SESS_CLI_MSG_CONT_SIZE 32 /* size of a multipart message in
- kilobytes (rounded upwards) */
-#define SESS_CLI_MSG_DATA 36
-/*---------------------------------------------------*/
-
-/* Client-to-session message types */
-#define SESS_CLI_CONNECT 1
-#define SESS_CLI_PREPARE 2
-#define SESS_CLI_EXECUTE 3
-#define SESS_CLI_BREAK_EXECUTION 4
-
-/* Client-to-session statement command types */
-#define SESS_COMM_FETCH_NEXT 1
-#define SESS_COMM_FETCH_PREV 2
-#define SESS_COMM_FETCH_FIRST 3
-#define SESS_COMM_FETCH_LAST 4
-#define SESS_COMM_FETCH_NTH 5
-#define SESS_COMM_FETCH_NTH_LAST 6
-#define SESS_COMM_EXECUTE 7
-#define SESS_COMM_NO_COMMAND 8
-
-/*---------------------------------------------------*/
-/* The format of an outgoing message from a session to the client */
-#define SESS_SRV_MSG_CHECKSUM 0 /* the checksum should be the first
- field in the message */
-#define SESS_SRV_MSG_SESS_ID 4
-#define SESS_SRV_MSG_TYPE 12
-#define SESS_SRV_MSG_NO 16
-#define SESS_SRV_MSG_CONTINUE 24 /* 0, or SESS_MSG_FIRST_PART
- SESS_MSG_MIDDLE_PART, or
- SESS_MSG_LAST_PART */
-#define SESS_SRV_MSG_CONT_SIZE 28 /* size of a multipart message
- in kilobytes (rounded upward) */
-#define SESS_SRV_MSG_DATA 32
-/*---------------------------------------------------*/
-
-/* Session-to-client message types */
-#define SESS_SRV_ACCEPT_CONNECT 1
-#define SESS_SRV_SUCCESS 2
-#define SESS_SRV_ERROR 3
-
-/* Multipart messages */
-#define SESS_MSG_SINGLE_PART 0
-#define SESS_MSG_FIRST_PART 1
-#define SESS_MSG_MIDDLE_PART 2
-#define SESS_MSG_LAST_PART 3
-
-/* Error numbers */
-#define SESS_ERR_NONE 0
-#define SESS_ERR_TRX_COMMITTED 1
-#define SESS_ERR_TRX_ROLLED_BACK 2
-#define SESS_ERR_SESSION_DISCONNECTED 3
-#define SESS_ERR_REPLY_FAILED 4
-#define SESS_ERR_CANNOT_BREAK_OP 5
-#define SESS_ERR_MSG_LOST 6
-#define SESS_ERR_MSG_CORRUPTED 7
-#define SESS_ERR_EXTRANEOUS_MSG 8
-#define SESS_ERR_OUT_OF_MEMORY 9
-#define SESS_ERR_SQL_ERROR 10
-#define SESS_ERR_STMT_NOT_FOUND 11
-#define SESS_ERR_STMT_NOT_READY 12
-#define SESS_ERR_EXTRANEOUS_SRV_MSG 13
-#define SESS_ERR_BREAK_BY_CLIENT 14
-
/* Session states */
#define SESS_ACTIVE 1
#define SESS_ERROR 2 /* session contains an error message
which has not yet been communicated
to the client */
-/* Session system states */
-#define SESS_SYS_RUNNING 1
-#define SESS_SYS_SHUTTING_DOWN 2
-
-/* Session hash table size */
-#define SESS_HASH_SIZE 1024
-
-/* Flags used in sess_srv_msg_send */
-#define SESS_RELEASE_KERNEL 1
-#define SESS_NOT_RELEASE_KERNEL 2
-
#ifndef UNIV_NONINL
#include "usr0sess.ic"
#endif
diff --git a/innobase/include/usr0sess.ic b/innobase/include/usr0sess.ic
index ee2592c7963..c851d5745b9 100644
--- a/innobase/include/usr0sess.ic
+++ b/innobase/include/usr0sess.ic
@@ -5,27 +5,3 @@ Sessions
Created 6/25/1996 Heikki Tuuri
*******************************************************/
-
-/***************************************************************************
-Sets the message type of a message from the client. */
-UNIV_INLINE
-void
-sess_cli_msg_set_type(
-/*==================*/
- byte* str, /* in: message string */
- ulint type) /* in: message type */
-{
- mach_write_to_4(str + SESS_CLI_MSG_TYPE, type);
-}
-
-/***************************************************************************
-Gets the message type of a message from the server. */
-UNIV_INLINE
-ulint
-sess_srv_msg_get_type(
-/*==================*/
- /* out: message type */
- byte* str) /* in: message string */
-{
- return(mach_read_from_4(str + SESS_SRV_MSG_TYPE));
-}
diff --git a/innobase/include/usr0types.h b/innobase/include/usr0types.h
index 67070ccce27..29359425169 100644
--- a/innobase/include/usr0types.h
+++ b/innobase/include/usr0types.h
@@ -10,7 +10,5 @@ Created 6/25/1996 Heikki Tuuri
#define usr0types_h
typedef struct sess_struct sess_t;
-typedef struct sess_sys_struct sess_sys_t;
-typedef struct sess_sig_struct sess_sig_t;
#endif
diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h
index 9b07d5da488..085b4811a73 100644
--- a/innobase/include/ut0dbg.h
+++ b/innobase/include/ut0dbg.h
@@ -10,7 +10,6 @@ Created 1/30/1994 Heikki Tuuri
#define ut0dbg_h
#include "univ.i"
-#include <assert.h>
#include <stdlib.h>
#include "os0thread.h"
@@ -24,7 +23,7 @@ extern const char* ut_dbg_msg_assert_fail;
extern const char* ut_dbg_msg_trap;
extern const char* ut_dbg_msg_stop;
-#define ut_a(EXPR)\
+#define ut_a(EXPR) do {\
if (!((ulint)(EXPR) + ut_dbg_zero)) {\
ut_print_timestamp(stderr);\
fprintf(stderr, ut_dbg_msg_assert_fail,\
@@ -33,38 +32,32 @@ extern const char* ut_dbg_msg_stop;
fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\
fputs(ut_dbg_msg_trap, stderr);\
ut_dbg_stop_threads = TRUE;\
- (*ut_dbg_null_ptr)++;\
+ if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\
}\
if (ut_dbg_stop_threads) {\
fprintf(stderr, ut_dbg_msg_stop,\
os_thread_pf(os_thread_get_curr_id()), IB__FILE__, (ulint)__LINE__);\
os_thread_sleep(1000000000);\
- }
+ }\
+} while (0)
-#define ut_error\
+#define ut_error do {\
ut_print_timestamp(stderr);\
fprintf(stderr, ut_dbg_msg_assert_fail,\
os_thread_pf(os_thread_get_curr_id()), IB__FILE__, (ulint)__LINE__);\
fprintf(stderr, ut_dbg_msg_trap);\
ut_dbg_stop_threads = TRUE;\
- (*ut_dbg_null_ptr)++;
+ if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\
+} while (0)
#ifdef UNIV_DEBUG
#define ut_ad(EXPR) ut_a(EXPR)
-#define ut_d(EXPR) {EXPR;}
+#define ut_d(EXPR) do {EXPR;} while (0)
#else
#define ut_ad(EXPR)
#define ut_d(EXPR)
#endif
-
#define UT_NOT_USED(A) A = A
-
-
-
-
-
-
#endif
-
diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h
index ce8aabeca41..b7dfe77a08e 100644
--- a/innobase/include/ut0mem.h
+++ b/innobase/include/ut0mem.h
@@ -96,6 +96,15 @@ ut_str_catenate(
char* str1, /* in: null-terminated string */
char* str2); /* in: null-terminated string */
/**************************************************************************
+Return a copy of the given string. The returned string must be freed
+using mem_free. */
+
+char*
+ut_strdup(
+/*======*/
+ /* out, own: cnull-terminated string */
+ char* str); /* in: null-terminated string */
+/**************************************************************************
Checks if a null-terminated string contains a certain character. */
ibool
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 4e6abf32c9e..2430380d65c 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -953,7 +953,9 @@ lock_rec_get_next_on_page(
ulint space;
ulint page_no;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_type(lock) == LOCK_REC);
space = lock->un_member.rec_lock.space;
@@ -990,7 +992,9 @@ lock_rec_get_first_on_page_addr(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
lock = HASH_GET_FIRST(lock_sys->rec_hash,
lock_rec_hash(space, page_no));
@@ -1048,7 +1052,9 @@ lock_rec_get_first_on_page(
ulint space;
ulint page_no;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
hash = buf_frame_get_lock_hash_val(ptr);
@@ -1080,7 +1086,9 @@ lock_rec_get_next(
rec_t* rec, /* in: record on a page */
lock_t* lock) /* in: lock */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_type(lock) == LOCK_REC);
for (;;) {
@@ -1109,7 +1117,9 @@ lock_rec_get_first(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first_on_page(rec);
@@ -1197,7 +1207,9 @@ lock_rec_get_prev(
ulint page_no;
lock_t* found_lock = NULL;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_type(in_lock) == LOCK_REC);
space = in_lock->un_member.rec_lock.space;
@@ -1237,7 +1249,9 @@ lock_table_has(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
/* Look for stronger locks the same trx already has on the table */
@@ -1281,7 +1295,9 @@ lock_rec_has_expl(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S
|| (precise_mode & LOCK_MODE_MASK) == LOCK_X);
ut_ad(!(precise_mode & LOCK_INSERT_INTENTION));
@@ -1328,7 +1344,9 @@ lock_rec_other_has_expl_req(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(mode == LOCK_X || mode == LOCK_S);
ut_ad(gap == 0 || gap == LOCK_GAP);
ut_ad(wait == 0 || wait == LOCK_WAIT);
@@ -1367,7 +1385,9 @@ lock_rec_other_has_conflicting(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
@@ -1399,7 +1419,9 @@ lock_rec_find_similar_on_page(
lock_t* lock;
ulint heap_no;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
heap_no = rec_get_heap_no(rec);
@@ -1433,7 +1455,9 @@ lock_sec_rec_some_has_impl_off_kernel(
{
page_t* page;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(!(index->type & DICT_CLUSTERED));
ut_ad(page_rec_is_user_rec(rec));
@@ -1491,7 +1515,9 @@ lock_rec_create(
ulint n_bits;
ulint n_bytes;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
page = buf_frame_align(rec);
space = buf_frame_get_space_id(page);
@@ -1575,7 +1601,9 @@ lock_rec_enqueue_waiting(
lock_t* lock;
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
/* Test if there already is some other reason to suspend thread:
we do not enqueue a lock request if the query thread should be
@@ -1583,7 +1611,7 @@ lock_rec_enqueue_waiting(
if (que_thr_stop(thr)) {
- ut_a(0);
+ ut_error;
return(DB_QUE_THR_SUSPENDED);
}
@@ -1661,7 +1689,9 @@ lock_rec_add_to_queue(
page_t* page;
ibool somebody_waits = FALSE;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_S)
|| !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, rec, trx));
@@ -1741,7 +1771,9 @@ lock_rec_lock_fast(
lock_t* lock;
ulint heap_no;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
@@ -1805,7 +1837,9 @@ lock_rec_lock_slow(
trx_t* trx;
ulint err;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
@@ -1867,7 +1901,9 @@ lock_rec_lock(
{
ulint err;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
@@ -1905,7 +1941,9 @@ lock_rec_has_to_wait_in_queue(
ulint page_no;
ulint heap_no;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_wait(wait_lock));
ut_ad(lock_get_type(wait_lock) == LOCK_REC);
@@ -1938,7 +1976,9 @@ lock_grant(
/*=======*/
lock_t* lock) /* in: waiting lock request */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
lock_reset_lock_and_trx_wait(lock);
@@ -1980,7 +2020,9 @@ lock_rec_cancel(
/*============*/
lock_t* lock) /* in: waiting record lock request */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_type(lock) == LOCK_REC);
/* Reset the bit (there can be only one set bit) in the lock bitmap */
@@ -2013,7 +2055,9 @@ lock_rec_dequeue_from_page(
lock_t* lock;
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_type(in_lock) == LOCK_REC);
trx = in_lock->trx;
@@ -2056,7 +2100,9 @@ lock_rec_discard(
ulint page_no;
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_type(in_lock) == LOCK_REC);
trx = in_lock->trx;
@@ -2085,7 +2131,9 @@ lock_rec_free_all_from_discard_page(
lock_t* lock;
lock_t* next_lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
space = buf_frame_get_space_id(page);
page_no = buf_frame_get_page_no(page);
@@ -2118,7 +2166,9 @@ lock_rec_reset_and_release_wait(
lock_t* lock;
ulint heap_no;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
heap_no = rec_get_heap_no(rec);
@@ -2150,7 +2200,9 @@ lock_rec_inherit_to_gap(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
@@ -2180,7 +2232,9 @@ lock_rec_inherit_to_gap_if_gap_lock(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
@@ -2213,7 +2267,9 @@ lock_rec_move(
ulint heap_no;
ulint type_mode;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
heap_no = rec_get_heap_no(donator);
@@ -2849,7 +2905,9 @@ lock_deadlock_occurs(
char* err_buf;
ut_ad(trx && lock);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
retry:
/* We check that adding this trx to the waits-for graph
does not produce a cycle. First mark all active transactions
@@ -2925,7 +2983,9 @@ lock_deadlock_recursive(
ulint ret;
ut_a(trx && start && wait_lock);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (trx->deadlock_mark == 1) {
/* We have already exhaustively searched the subtree starting
@@ -3116,7 +3176,9 @@ lock_table_create(
lock_t* lock;
ut_ad(table && trx);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (type_mode == LOCK_AUTO_INC) {
/* Only one trx can have the lock on the table
@@ -3166,7 +3228,9 @@ lock_table_remove_low(
dict_table_t* table;
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
table = lock->un_member.tab_lock.table;
trx = lock->trx;
@@ -3200,14 +3264,16 @@ lock_table_enqueue_waiting(
lock_t* lock;
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
/* Test if there already is some other reason to suspend thread:
we do not enqueue a lock request if the query thread should be
stopped anyway */
if (que_thr_stop(thr)) {
- ut_a(0);
+ ut_error;
return(DB_QUE_THR_SUSPENDED);
}
@@ -3270,7 +3336,9 @@ lock_table_other_has_incompatible(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
lock = UT_LIST_GET_LAST(table->locks);
@@ -3420,7 +3488,9 @@ lock_table_dequeue(
{
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_type(in_lock) == LOCK_TABLE);
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
@@ -3476,7 +3546,9 @@ lock_release_off_kernel(
ulint count;
lock_t* lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
lock = UT_LIST_GET_LAST(trx->trx_locks);
@@ -3537,7 +3609,9 @@ lock_cancel_waiting_and_release(
/*============================*/
lock_t* lock) /* in: waiting lock request */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (lock_get_type(lock) == LOCK_REC) {
@@ -3570,7 +3644,9 @@ lock_reset_all_on_table_for_trx(
lock_t* lock;
lock_t* prev_lock;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
lock = UT_LIST_GET_LAST(trx->trx_locks);
@@ -3632,7 +3708,9 @@ lock_table_print(
500 bytes */
lock_t* lock) /* in: table type lock */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(lock_get_type(lock) == LOCK_TABLE);
buf += sprintf(buf, "TABLE LOCK table %s trx id %lu %lu",
@@ -3679,7 +3757,9 @@ lock_rec_print(
char* buf_start = buf;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(lock_get_type(lock) == LOCK_REC);
space = lock->un_member.rec_lock.space;
@@ -3743,7 +3823,9 @@ lock_rec_print(
}
if (page) {
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
}
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
@@ -3788,7 +3870,9 @@ lock_get_n_rec_locks(void)
ulint n_locks = 0;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
@@ -4060,7 +4144,9 @@ lock_table_queue_validate(
lock_t* lock;
ibool is_waiting;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
is_waiting = FALSE;
@@ -4213,12 +4299,16 @@ lock_rec_validate_page(
ulint i;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
mtr_start(&mtr);
page = buf_page_get(space, page_no, RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
lock_mutex_enter_kernel();
loop:
@@ -4464,7 +4554,9 @@ lock_rec_convert_impl_to_expl(
{
trx_t* impl_trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(page_rec_is_user_rec(rec));
if (index->type & DICT_CLUSTERED) {
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index a40be74cac2..e99ea269920 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -32,7 +32,9 @@ ulint log_fsp_current_free_limit = 0;
log_t* log_sys = NULL;
ibool log_do_write = TRUE;
+#ifdef UNIV_LOG_DEBUG
ibool log_debug_writes = FALSE;
+#endif /* UNIV_LOG_DEBUG */
/* These control how often we print warnings if the last checkpoint is too
old */
@@ -86,9 +88,8 @@ the previous */
Completes a checkpoint write i/o to a log file. */
static
void
-log_io_complete_checkpoint(
-/*=======================*/
- log_group_t* group); /* in: log group */
+log_io_complete_checkpoint(void);
+/*============================*/
/**********************************************************
Completes an archiving i/o. */
static
@@ -133,7 +134,9 @@ log_buf_pool_get_oldest_modification(void)
{
dulint lsn;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
lsn = buf_pool_get_oldest_modification();
@@ -231,7 +234,9 @@ log_write_low(
ulint data_len;
byte* log_block;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
part_loop:
/* Calculate a part length */
@@ -298,7 +303,9 @@ log_close(void)
log_t* log = log_sys;
ulint checkpoint_age;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
lsn = log->lsn;
@@ -414,7 +421,9 @@ log_group_get_capacity(
/* out: capacity in bytes */
log_group_t* group) /* in: log group */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
return((group->file_size - LOG_FILE_HDR_SIZE) * group->n_files);
}
@@ -430,7 +439,9 @@ log_group_calc_size_offset(
ulint offset, /* in: real offset within the log group */
log_group_t* group) /* in: log group */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
return(offset - LOG_FILE_HDR_SIZE * (1 + offset / group->file_size));
}
@@ -446,7 +457,9 @@ log_group_calc_real_offset(
ulint offset, /* in: size offset within the log group */
log_group_t* group) /* in: log group */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
return(offset + LOG_FILE_HDR_SIZE
* (1 + offset / (group->file_size - LOG_FILE_HDR_SIZE)));
@@ -469,7 +482,9 @@ log_group_calc_lsn_offset(
ib_longlong group_size;
ib_longlong offset;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
/* If total log file size is > 2 GB we can easily get overflows
with 32-bit integers. Use 64-bit integers instead. */
@@ -583,7 +598,9 @@ log_calc_max_ages(void)
ulint archive_margin;
ulint smallest_archive_margin;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(log_sys->mutex));
@@ -873,7 +890,9 @@ log_flush_do_unlocks(
ulint code) /* in: any ORed combination of LOG_UNLOCK_FLUSH_LOCK
and LOG_UNLOCK_NONE_FLUSHED_LOCK */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
/* NOTE that we must own the log mutex when doing the setting of the
events: this is because transactions will wait for these events to
@@ -905,14 +924,17 @@ log_group_check_flush_completion(
/* out: LOG_UNLOCK_NONE_FLUSHED_LOCK or 0 */
log_group_t* group) /* in: log group */
{
- ut_ad(mutex_own(&(log_sys->mutex)));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (!log_sys->one_flushed && group->n_pending_writes == 0) {
-
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf("Log flushed first to group %lu\n",
(ulong) group->id);
}
+#endif /* UNIV_LOG_DEBUG */
log_sys->written_to_some_lsn = log_sys->write_lsn;
log_sys->one_flushed = TRUE;
@@ -920,10 +942,12 @@ log_group_check_flush_completion(
return(LOG_UNLOCK_NONE_FLUSHED_LOCK);
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes && (group->n_pending_writes == 0)) {
printf("Log flushed to group %lu\n", (ulong) group->id);
}
+#endif /* UNIV_LOG_DEBUG */
return(0);
}
@@ -939,7 +963,9 @@ log_sys_check_flush_completion(void)
ulint move_start;
ulint move_end;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (log_sys->n_pending_writes == 0) {
@@ -997,12 +1023,20 @@ log_io_complete(
fil_flush(group->space_id);
}
- log_io_complete_checkpoint(group);
+#ifdef UNIV_LOG_DEBUG
+ if (log_debug_writes) {
+ fprintf(stderr,
+ "Checkpoint info written to group %lu\n",
+ group->id);
+ }
+#endif /* UNIV_LOG_DEBUG */
+
+ log_io_complete_checkpoint();
return;
}
- ut_a(0); /* We currently use synchronous writing of the
+ ut_error; /* We currently use synchronous writing of the
logs and cannot end up here! */
if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC
@@ -1046,7 +1080,9 @@ log_group_file_header_flush(
UT_NOT_USED(type);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(nth_file < group->n_files);
@@ -1060,11 +1096,13 @@ log_group_file_header_flush(
dest_offset = nth_file * group->file_size;
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf(
"Writing log file header to group %lu file %lu\n",
(ulong) group->id, (ulong) nth_file);
}
+#endif /* UNIV_LOG_DEBUG */
if (log_do_write) {
log_sys->n_log_ios++;
@@ -1114,7 +1152,9 @@ log_group_write_buf(
ulint next_offset;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
@@ -1147,6 +1187,7 @@ loop:
write_len = len;
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf(
@@ -1171,6 +1212,7 @@ loop:
+ i * OS_FILE_LOG_BLOCK_SIZE));
}
}
+#endif /* UNIV_LOG_DEBUG */
/* Calculate the checksums for each log block and write them to
the trailer fields of the log blocks */
@@ -1298,6 +1340,7 @@ loop:
return;
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf("Writing log from %lu %lu up to lsn %lu %lu\n",
(ulong) ut_dulint_get_high(log_sys->written_to_all_lsn),
@@ -1305,6 +1348,7 @@ loop:
(ulong) ut_dulint_get_high(log_sys->lsn),
(ulong) ut_dulint_get_low(log_sys->lsn));
}
+#endif /* UNIV_LOG_DEBUG */
log_sys->n_pending_writes++;
@@ -1513,7 +1557,9 @@ void
log_complete_checkpoint(void)
/*=========================*/
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(log_sys->n_pending_checkpoint_writes == 0);
log_sys->next_checkpoint_no
@@ -1528,9 +1574,8 @@ log_complete_checkpoint(void)
Completes an asynchronous checkpoint info write i/o to a log file. */
static
void
-log_io_complete_checkpoint(
-/*=======================*/
- log_group_t* group) /* in: log group */
+log_io_complete_checkpoint(void)
+/*============================*/
{
mutex_enter(&(log_sys->mutex));
@@ -1538,11 +1583,6 @@ log_io_complete_checkpoint(
log_sys->n_pending_checkpoint_writes--;
- if (log_debug_writes) {
- printf("Checkpoint info written to group %lu\n",
- (ulong) group->id);
- }
-
if (log_sys->n_pending_checkpoint_writes == 0) {
log_complete_checkpoint();
}
@@ -1604,7 +1644,9 @@ log_group_checkpoint(
byte* buf;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE);
buf = group->checkpoint_buf;
@@ -1758,7 +1800,9 @@ log_group_read_checkpoint_info(
log_group_t* group, /* in: log group */
ulint field) /* in: LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2 */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
log_sys->n_log_ios++;
@@ -1776,7 +1820,9 @@ log_groups_write_checkpoint_info(void)
{
log_group_t* group;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -1861,12 +1907,14 @@ log_checkpoint(
log_sys->next_checkpoint_lsn = oldest_lsn;
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf("Making checkpoint no %lu at lsn %lu %lu\n",
(ulong) ut_dulint_get_low(log_sys->next_checkpoint_no),
(ulong) ut_dulint_get_high(oldest_lsn),
(ulong) ut_dulint_get_low(oldest_lsn));
}
+#endif /* UNIV_LOG_DEBUG */
log_groups_write_checkpoint_info();
@@ -2041,7 +2089,9 @@ log_group_read_log_seg(
ulint source_offset;
ibool sync;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
sync = FALSE;
@@ -2113,9 +2163,11 @@ log_group_archive_file_header_write(
byte* buf;
ulint dest_offset;
+#ifdef UNIV_SYNC_DEBUG
ut_a(0);
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(nth_file < group->n_files);
@@ -2152,9 +2204,11 @@ log_group_archive_completed_header_write(
byte* buf;
ulint dest_offset;
+#ifdef UNIV_SYNC_DEBUG
ut_a(0);
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(nth_file < group->n_files);
buf = *(group->archive_file_header_bufs + nth_file);
@@ -2193,9 +2247,11 @@ log_group_archive(
ulint n_files;
ulint open_mode;
+#ifdef UNIV_SYNC_DEBUG
ut_a(0);
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
start_lsn = log_sys->archived_lsn;
@@ -2245,9 +2301,11 @@ loop:
exit(1);
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf("Created archive file %s\n", name);
}
+#endif /* UNIV_LOG_DEBUG */
ret = os_file_close(file_handle);
@@ -2274,6 +2332,7 @@ loop:
len = group->file_size - (next_offset % group->file_size);
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf(
"Archiving starting at lsn %lu %lu, len %lu to group %lu\n",
@@ -2281,6 +2340,7 @@ loop:
(ulong) ut_dulint_get_low(start_lsn),
(ulong) len, (ulong) group->id);
}
+#endif /* UNIV_LOG_DEBUG */
log_sys->n_pending_archive_ios++;
@@ -2320,9 +2380,11 @@ log_archive_groups(void)
{
log_group_t* group;
+#ifdef UNIV_SYNC_DEBUG
ut_a(0);
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -2345,9 +2407,11 @@ log_archive_write_complete_groups(void)
dulint end_lsn;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_a(0);
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -2371,10 +2435,12 @@ log_archive_write_complete_groups(void)
trunc_files = n_files - 1;
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes && trunc_files) {
printf("Complete file(s) archived to group %lu\n",
(ulong) group->id);
}
+#endif /* UNIV_LOG_DEBUG */
/* Calculate the archive file space start lsn */
start_lsn = ut_dulint_subtract(log_sys->next_archived_lsn,
@@ -2397,9 +2463,11 @@ log_archive_write_complete_groups(void)
fil_space_truncate_start(group->archive_space_id,
trunc_files * group->file_size);
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf("Archiving writes completed\n");
}
+#endif /* UNIV_LOG_DEBUG */
}
/**********************************************************
@@ -2409,16 +2477,20 @@ void
log_archive_check_completion_low(void)
/*==================================*/
{
+#ifdef UNIV_SYNC_DEBUG
ut_a(0);
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (log_sys->n_pending_archive_ios == 0
&& log_sys->archiving_phase == LOG_ARCHIVE_READ) {
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf("Archiving read completed\n");
}
+#endif /* UNIV_LOG_DEBUG */
/* Archive buffer has now been read in: start archive writes */
@@ -2512,8 +2584,7 @@ loop:
start_lsn = log_sys->archived_lsn;
if (calc_new_limit) {
- ut_a(log_sys->archive_buf_size % OS_FILE_LOG_BLOCK_SIZE
- == 0);
+ ut_a(log_sys->archive_buf_size % OS_FILE_LOG_BLOCK_SIZE == 0);
limit_lsn = ut_dulint_add(start_lsn,
log_sys->archive_buf_size);
@@ -2567,6 +2638,7 @@ loop:
log_sys->next_archived_lsn = limit_lsn;
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf("Archiving from lsn %lu %lu to lsn %lu %lu\n",
(ulong) ut_dulint_get_high(log_sys->archived_lsn),
@@ -2574,6 +2646,7 @@ loop:
(ulong) ut_dulint_get_high(limit_lsn),
(ulong) ut_dulint_get_low(limit_lsn));
}
+#endif /* UNIV_LOG_DEBUG */
/* Read the log segment to the archive buffer */
@@ -2649,7 +2722,9 @@ log_archive_close_groups(
log_group_t* group;
ulint trunc_len;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (log_sys->archiving_state == LOG_ARCH_OFF) {
@@ -2678,12 +2753,14 @@ log_archive_close_groups(
group->archived_file_no += 2;
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
printf(
"Incrementing arch file no to %lu in log group %lu\n",
(ulong) group->archived_file_no + 2,
(ulong) group->id);
}
+#endif /* UNIV_LOG_DEBUG */
}
}
@@ -3153,6 +3230,7 @@ loop:
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
}
+#ifdef UNIV_LOG_DEBUG
/**********************************************************
Checks by parsing that the catenated log segment for a single mtr is
consistent. */
@@ -3172,7 +3250,9 @@ log_check_log_recs(
byte* buf1;
byte* scan_buf;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (len == 0) {
@@ -3203,6 +3283,7 @@ log_check_log_recs(
return(TRUE);
}
+#endif /* UNIV_LOG_DEBUG */
/**********************************************************
Peeks the current lsn. */
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index 0a1115a6891..432a6ed1e85 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -165,14 +165,16 @@ void
recv_sys_empty_hash(void)
/*=====================*/
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(recv_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (recv_sys->n_addrs != 0) {
fprintf(stderr,
"InnoDB: Error: %lu pages with log records were left unprocessed!\n"
"InnoDB: Maximum page number with log records on it %lu\n",
(ulong) recv_sys->n_addrs,
(ulong) recv_max_parsed_page_no);
- ut_a(0);
+ ut_error;
}
hash_table_free(recv_sys->addr_hash);
@@ -485,6 +487,7 @@ recv_find_max_checkpoint(
log_group_read_checkpoint_info(group, field);
if (!recv_check_cp_is_consistent(buf)) {
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n",
@@ -494,6 +497,7 @@ recv_find_max_checkpoint(
+ LOG_CHECKPOINT_CHECKSUM_1));
}
+#endif /* UNIV_LOG_DEBUG */
goto not_consistent;
}
@@ -507,12 +511,14 @@ recv_find_max_checkpoint(
checkpoint_no =
mach_read_from_8(buf + LOG_CHECKPOINT_NO);
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Checkpoint number %lu found in group %lu\n",
(ulong) ut_dulint_get_low(checkpoint_no),
(ulong) group->id);
}
+#endif /* UNIV_LOG_DEBUG */
if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) {
*max_group = group;
@@ -1078,7 +1084,9 @@ recv_recover_page(
&mtr);
ut_a(success);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
}
/* Read the newest modification lsn from the page */
@@ -1143,6 +1151,7 @@ recv_recover_page(
start_lsn = recv->start_lsn;
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Applying log rec type %lu len %lu to space %lu page no %lu\n",
@@ -1150,7 +1159,8 @@ recv_recover_page(
(ulong) recv_addr->space,
(ulong) recv_addr->page_no);
}
-
+#endif /* UNIV_LOG_DEBUG */
+
recv_parse_or_apply_log_rec_body(recv->type, buf,
buf + recv->len, page, &mtr);
mach_write_to_8(page + UNIV_PAGE_SIZE
@@ -1280,14 +1290,13 @@ loop:
goto loop;
}
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!allow_ibuf == mutex_own(&log_sys->mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (!allow_ibuf) {
- ut_ad(mutex_own(&(log_sys->mutex)));
-
recv_no_ibuf_operations = TRUE;
- } else {
- ut_ad(!mutex_own(&(log_sys->mutex)));
}
-
+
recv_sys->apply_log_recs = TRUE;
recv_sys->apply_batch_on = TRUE;
@@ -1317,8 +1326,10 @@ loop:
page = buf_page_get(space, page_no,
RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page,
SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
recv_recover_page(FALSE, FALSE, page,
space, page_no);
mtr_commit(&mtr);
@@ -1541,7 +1552,9 @@ recv_update_replicate(
replica = buf_page_get(space + RECV_REPLICA_SPACE_ADD, page_no,
RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(replica, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
ptr = recv_parse_or_apply_log_rec_body(type, body, end_ptr, replica,
&mtr);
@@ -1610,7 +1623,9 @@ recv_compare_replicate(
replica = buf_page_get(space + RECV_REPLICA_SPACE_ADD, page_no,
RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(replica, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
recv_check_identical(page + FIL_PAGE_DATA,
replica + FIL_PAGE_DATA,
@@ -1651,7 +1666,9 @@ recv_compare_spaces(
IB__FILE__, __LINE__,
&mtr);
if (frame) {
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(frame, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
ut_memcpy(page, frame, UNIV_PAGE_SIZE);
} else {
/* Read it from file */
@@ -1664,7 +1681,9 @@ recv_compare_spaces(
IB__FILE__, __LINE__,
&mtr);
if (frame) {
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(frame, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
ut_memcpy(replica, frame, UNIV_PAGE_SIZE);
} else {
/* Read it from file */
@@ -1916,7 +1935,9 @@ recv_parse_log_recs(
byte* body;
ulint n_recs;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(!ut_dulint_is_zero(recv_sys->parse_start_lsn));
loop:
ptr = recv_sys->buf + recv_sys->recovered_offset;
@@ -1969,12 +1990,14 @@ loop:
recv_sys->recovered_offset += len;
recv_sys->recovered_lsn = new_recovered_lsn;
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Parsed a single log rec type %lu len %lu space %lu page no %lu\n",
(ulong) type, (ulong) len, (ulong) space,
(ulong) page_no);
}
+#endif /* UNIV_LOG_DEBUG */
if (type == MLOG_DUMMY_RECORD) {
/* Do nothing */
@@ -2056,13 +2079,15 @@ loop:
*/
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Parsed a multi log rec type %lu len %lu space %lu page no %lu\n",
(ulong) type, (ulong) len, (ulong) space,
(ulong) page_no);
}
-
+#endif /* UNIV_LOG_DEBUG */
+
total_len += len;
n_recs++;
@@ -2467,6 +2492,7 @@ recv_group_scan_log_recs(
start_lsn = end_lsn;
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Scanned group %lu up to log sequence number %lu %lu\n",
@@ -2474,6 +2500,7 @@ recv_group_scan_log_recs(
(ulong) ut_dulint_get_high(*group_scanned_lsn),
(ulong) ut_dulint_get_low(*group_scanned_lsn));
}
+#endif /* UNIV_LOG_DEBUG */
}
/************************************************************
@@ -2854,10 +2881,12 @@ recv_recovery_from_checkpoint_finish(void)
recv_apply_hashed_log_recs(TRUE);
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Log records applied to the database\n");
}
+#endif /* UNIV_LOG_DEBUG */
if (recv_needed_recovery) {
trx_sys_print_mysql_master_log_pos();
@@ -2899,8 +2928,9 @@ recv_reset_logs(
{
log_group_t* group;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
log_sys->lsn = ut_dulint_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE);
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -3168,6 +3198,7 @@ ask_again:
break;
}
+#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Archive read starting at lsn %lu %lu, len %lu from file %s\n",
@@ -3175,6 +3206,7 @@ ask_again:
(ulong) ut_dulint_get_low(start_lsn),
(ulong) len, name);
}
+#endif /* UNIV_LOG_DEBUG */
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE,
group->archive_space_id, read_offset / UNIV_PAGE_SIZE,
diff --git a/innobase/mem/mem0dbg.c b/innobase/mem/mem0dbg.c
index 89ca68a1232..1007f8413b4 100644
--- a/innobase/mem/mem0dbg.c
+++ b/innobase/mem/mem0dbg.c
@@ -7,6 +7,7 @@ but is included in mem0mem.* !
Created 6/9/1994 Heikki Tuuri
*************************************************************************/
+#ifdef UNIV_MEM_DEBUG
mutex_t mem_hash_mutex; /* The mutex which protects in the
debug version the hash table containing
the list of live memory heaps, and
@@ -16,12 +17,11 @@ mutex_t mem_hash_mutex; /* The mutex which protects in the
extent of memory allocations. Only used in the debug version.
Protected by mem_hash_mutex above. */
-ulint mem_n_created_heaps = 0;
-ulint mem_n_allocations = 0;
-ulint mem_total_allocated_memory = 0;
-ulint mem_current_allocated_memory = 0;
-ulint mem_max_allocated_memory = 0;
-ulint mem_last_print_info = 0;
+static ulint mem_n_created_heaps = 0;
+static ulint mem_n_allocations = 0;
+static ulint mem_total_allocated_memory = 0;
+static ulint mem_current_allocated_memory = 0;
+static ulint mem_max_allocated_memory = 0;
/* Size of the hash table for memory management tracking */
#define MEM_HASH_SIZE 997
@@ -43,12 +43,12 @@ struct mem_hash_node_struct {
typedef UT_LIST_BASE_NODE_T(mem_hash_node_t) mem_hash_cell_t;
/* The hash table of allocated heaps */
-mem_hash_cell_t mem_hash_table[MEM_HASH_SIZE];
+static mem_hash_cell_t mem_hash_table[MEM_HASH_SIZE];
/* The base node of the list of all allocated heaps */
-mem_hash_cell_t mem_all_list_base;
+static mem_hash_cell_t mem_all_list_base;
-ibool mem_hash_initialized = FALSE;
+static ibool mem_hash_initialized = FALSE;
UNIV_INLINE
@@ -65,45 +65,44 @@ mem_hash_get_nth_cell(ulint i)
return(&(mem_hash_table[i]));
}
+#endif /* UNIV_MEM_DEBUG */
/* Accessor functions for a memory field in the debug version */
void
mem_field_header_set_len(byte* field, ulint len)
{
- ut_ad(len >= 0);
-
- mach_write(field - 2 * sizeof(ulint), len);
+ mach_write_to_4(field - 2 * sizeof(ulint), len);
}
ulint
mem_field_header_get_len(byte* field)
{
- return(mach_read(field - 2 * sizeof(ulint)));
+ return(mach_read_from_4(field - 2 * sizeof(ulint)));
}
void
mem_field_header_set_check(byte* field, ulint check)
{
- mach_write(field - sizeof(ulint), check);
+ mach_write_to_4(field - sizeof(ulint), check);
}
ulint
mem_field_header_get_check(byte* field)
{
- return(mach_read(field - sizeof(ulint)));
+ return(mach_read_from_4(field - sizeof(ulint)));
}
void
mem_field_trailer_set_check(byte* field, ulint check)
{
- mach_write(field + mem_field_header_get_len(field), check);
+ mach_write_to_4(field + mem_field_header_get_len(field), check);
}
ulint
mem_field_trailer_get_check(byte* field)
{
- return(mach_read(field +
+ return(mach_read_from_4(field +
mem_field_header_get_len(field)));
}
@@ -164,6 +163,7 @@ mem_field_init(
mem_field_header_set_check(usr_buf, rnd);
mem_field_trailer_set_check(usr_buf, rnd);
+#ifdef UNIV_MEM_DEBUG
/* Update the memory allocation information */
mutex_enter(&mem_hash_mutex);
@@ -182,6 +182,7 @@ mem_field_init(
combination of 0xBA and 0xBE */
mem_init_buf(usr_buf, n);
+#endif /* UNIV_MEM_DEBUG */
}
/**********************************************************************
@@ -191,12 +192,14 @@ void
mem_field_erase(
/*============*/
byte* buf, /* in: memory field */
- ulint n) /* in: how many bytes the user requested */
+ ulint n __attribute__((unused)))
+ /* in: how many bytes the user requested */
{
byte* usr_buf;
usr_buf = buf + MEM_FIELD_HEADER_SIZE;
-
+
+#ifdef UNIV_MEM_DEBUG
mutex_enter(&mem_hash_mutex);
mem_current_allocated_memory -= n;
mutex_exit(&mem_hash_mutex);
@@ -208,8 +211,10 @@ mem_field_erase(
combination of 0xDE and 0xAD */
mem_erase_buf(buf, MEM_SPACE_NEEDED(n));
+#endif /* UNIV_MEM_DEBUG */
}
+#ifdef UNIV_MEM_DEBUG
/*******************************************************************
Initializes a buffer to a random combination of hex BA and BE.
Used to initialize allocated memory. */
@@ -372,6 +377,7 @@ mem_hash_remove(
mutex_exit(&mem_hash_mutex);
}
+#endif /* UNIV_MEM_DEBUG */
/*******************************************************************
Checks a memory heap for consistency and prints the contents if requested.
diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c
index 2817e1f12d4..4f1ac2bcd7c 100644
--- a/innobase/mem/mem0pool.c
+++ b/innobase/mem/mem0pool.c
@@ -259,7 +259,9 @@ mem_pool_fill_free_list(
mem_area_t* area2;
ibool ret;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (i >= 63) {
/* We come here when we have run out of space in the
@@ -296,7 +298,7 @@ mem_pool_fill_free_list(
if (UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0) {
mem_analyze_corruption((byte*)area);
- ut_a(0);
+ ut_error;
}
UT_LIST_REMOVE(free_list, pool->free_list[i + 1], area);
@@ -374,7 +376,7 @@ mem_area_alloc(
"InnoDB: Probably a race condition because now the area is marked free!\n");
}
- ut_a(0);
+ ut_error;
}
if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) {
@@ -384,7 +386,7 @@ mem_area_alloc(
(ulong) n);
mem_analyze_corruption((byte*)area);
- ut_a(0);
+ ut_error;
}
ut_ad(mem_area_get_size(area) == ut_2_exp(n));
@@ -480,7 +482,7 @@ mem_area_free(
"InnoDB: element is marked free!\n");
mem_analyze_corruption((byte*)area);
- ut_a(0);
+ ut_error;
}
size = mem_area_get_size(area);
@@ -491,7 +493,7 @@ mem_area_free(
"InnoDB: previous allocated area!\n");
mem_analyze_corruption((byte*)area);
- ut_a(0);
+ ut_error;
}
#ifdef UNIV_LIGHT_MEM_DEBUG
@@ -508,7 +510,7 @@ mem_area_free(
(ulong) size, (ulong) next_size);
mem_analyze_corruption((byte*)area);
- ut_a(0);
+ ut_error;
}
}
#endif
diff --git a/innobase/mtr/mtr0log.c b/innobase/mtr/mtr0log.c
index 4b5d7e61de6..5a4aaa2377d 100644
--- a/innobase/mtr/mtr0log.c
+++ b/innobase/mtr/mtr0log.c
@@ -59,7 +59,7 @@ mlog_write_initial_log_record(
fprintf(stderr,
"InnoDB: Error: trying to write to a stray memory location %lx\n",
(ulong) ptr);
- ut_a(0);
+ ut_error;
}
log_ptr = mlog_open(mtr, 20);
@@ -222,7 +222,7 @@ mlog_write_ulint(
fprintf(stderr,
"InnoDB: Error: trying to write to a stray memory location %lx\n",
(ulong) ptr);
- ut_a(0);
+ ut_error;
}
if (type == MLOG_1BYTE) {
@@ -261,7 +261,6 @@ mlog_write_dulint(
/*==============*/
byte* ptr, /* in: pointer where to write */
dulint val, /* in: value to write */
- byte type, /* in: MLOG_8BYTES */
mtr_t* mtr) /* in: mini-transaction handle */
{
byte* log_ptr;
@@ -270,11 +269,10 @@ mlog_write_dulint(
fprintf(stderr,
"InnoDB: Error: trying to write to a stray memory location %lx\n",
(ulong) ptr);
- ut_a(0);
+ ut_error;
}
ut_ad(ptr && mtr);
- ut_ad(type == MLOG_8BYTES);
mach_write_to_8(ptr, val);
@@ -286,7 +284,8 @@ mlog_write_dulint(
return;
}
- log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr);
+ log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_8BYTES,
+ log_ptr, mtr);
mach_write_to_2(log_ptr, ptr - buf_frame_align(ptr));
log_ptr += 2;
@@ -314,7 +313,7 @@ mlog_write_string(
fprintf(stderr,
"InnoDB: Error: trying to write to a stray memory location %lx\n",
(ulong) ptr);
- ut_a(0);
+ ut_error;
}
ut_ad(ptr && mtr);
ut_a(len < UNIV_PAGE_SIZE);
diff --git a/innobase/mtr/mtr0mtr.c b/innobase/mtr/mtr0mtr.c
index 60e3ecfe150..ac1a638063d 100644
--- a/innobase/mtr/mtr0mtr.c
+++ b/innobase/mtr/mtr0mtr.c
@@ -495,13 +495,11 @@ mtr_read_dulint(
/*===========*/
/* out: value read */
byte* ptr, /* in: pointer from where to read */
- ulint type __attribute__((unused)), /* in: MLOG_8BYTES */
mtr_t* mtr __attribute__((unused)))
/* in: mini-transaction handle */
{
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad(ptr && mtr);
- ut_ad(type == MLOG_8BYTES);
ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr),
MTR_MEMO_PAGE_S_FIX) ||
mtr_memo_contains(mtr, buf_block_align(ptr),
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index a87ab974b83..7973cfc6fe8 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -716,7 +716,9 @@ os_file_create_simple(
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
(if does not exist, error), or OS_FILE_CREATE if a new
- file is created (if exists, error) */
+ file is created (if exists, error), or
+ OS_FILE_CREATE_PATH if new file (if exists, error) and
+ subdirectories along its path are created (if needed)*/
ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */
ibool* success)/* out: TRUE if succeed, FALSE if error */
{
@@ -734,6 +736,14 @@ try_again:
create_flag = OPEN_EXISTING;
} else if (create_mode == OS_FILE_CREATE) {
create_flag = CREATE_NEW;
+ } else if (create_mode == OS_FILE_CREATE_PATH) {
+ /* create subdirs along the path if needed */
+ *success = os_file_create_subdirs_if_needed(name);
+ if (!*success) {
+ ut_error;
+ }
+ create_flag = CREATE_NEW;
+ create_mode = OS_FILE_CREATE;
} else {
create_flag = 0;
ut_error;
@@ -787,6 +797,14 @@ try_again:
}
} else if (create_mode == OS_FILE_CREATE) {
create_flag = O_RDWR | O_CREAT | O_EXCL;
+ } else if (create_mode == OS_FILE_CREATE_PATH) {
+ /* create subdirs along the path if needed */
+ *success = os_file_create_subdirs_if_needed(name);
+ if (!*success) {
+ return (-1);
+ }
+ create_flag = O_RDWR | O_CREAT | O_EXCL;
+ create_mode = OS_FILE_CREATE;
} else {
create_flag = 0;
ut_error;
@@ -1068,7 +1086,7 @@ try_again:
} else if (type == OS_DATA_FILE) {
type_str = "DATA";
} else {
- ut_a(0);
+ ut_error;
}
if (purpose == OS_FILE_AIO) {
@@ -1076,7 +1094,7 @@ try_again:
} else if (purpose == OS_FILE_NORMAL) {
purpose_str = "NORMAL";
} else {
- ut_a(0);
+ ut_error;
}
/* printf("Opening file %s, mode %s, type %s, purpose %s\n",
@@ -1558,7 +1576,7 @@ os_file_flush(
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
- ut_a(0);
+ ut_error;
return(FALSE);
#else
@@ -1593,7 +1611,7 @@ os_file_flush(
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
- ut_a(0);
+ ut_error;
return(FALSE);
#endif
@@ -2114,6 +2132,185 @@ retry:
#endif
}
+/***********************************************************************
+Check the existence and type of the given file. */
+
+ibool
+os_file_status(
+/*===========*/
+ /* out: TRUE if call succeeded */
+ char* path, /* in: pathname of the file */
+ ibool* exists, /* out: TRUE if file exists */
+ os_file_type_t* type) /* out: type of the file (if it exists) */
+{
+#ifdef __WIN__
+ int ret;
+ struct _stat statinfo;
+
+ ret = _stat(path, &statinfo);
+ if (ret && (errno == ENOENT || errno == ENOTDIR)) {
+ /* file does not exist */
+ *exists = FALSE;
+ return(TRUE);
+ } else if (ret) {
+ /* file exists, but stat call failed */
+
+ os_file_handle_error_no_exit(0, path, "stat");
+
+ return(FALSE);
+ }
+
+ if (_S_IFDIR & statinfo.st_mode) {
+ *type = OS_FILE_TYPE_DIR;
+ } else if (_S_IFREG & statinfo.st_mode) {
+ *type = OS_FILE_TYPE_FILE;
+ } else {
+ *type = OS_FILE_TYPE_UNKNOWN;
+ }
+
+ *exists = TRUE;
+
+ return(TRUE);
+#else
+ int ret;
+ struct stat statinfo;
+
+ ret = stat(path, &statinfo);
+ if (ret && (errno == ENOENT || errno == ENOTDIR)) {
+ /* file does not exist */
+ *exists = FALSE;
+ return(TRUE);
+ } else if (ret) {
+ /* file exists, but stat call failed */
+
+ os_file_handle_error_no_exit(0, path, "stat");
+
+ return(FALSE);
+ }
+
+ if (S_ISDIR(statinfo.st_mode)) {
+ *type = OS_FILE_TYPE_DIR;
+ } else if (S_ISLNK(statinfo.st_mode)) {
+ *type = OS_FILE_TYPE_LINK;
+ } else if (S_ISREG(statinfo.st_mode)) {
+ *type = OS_FILE_TYPE_FILE;
+ } else {
+ *type = OS_FILE_TYPE_UNKNOWN;
+ }
+
+ *exists = TRUE;
+
+ return(TRUE);
+#endif
+}
+
+/* path name separator character */
+#ifdef __WIN__
+# define OS_FILE_PATH_SEPARATOR '\\'
+#else
+# define OS_FILE_PATH_SEPARATOR '/'
+#endif
+
+/********************************************************************
+The function os_file_dirname returns a directory component of a
+null-terminated pathname string. In the usual case, dirname returns
+the string up to, but not including, the final '/', and basename
+is the component following the final '/'. Trailing '/' charac­
+ters are not counted as part of the pathname.
+
+If path does not contain a slash, dirname returns the string ".".
+
+Concatenating the string returned by dirname, a "/", and the basename
+yields a complete pathname.
+
+The return value is a copy of the directory component of the pathname.
+The copy is allocated from heap. It is the caller responsibility
+to free it after it is no longer needed.
+
+The following list of examples (taken from SUSv2) shows the strings
+returned by dirname and basename for different paths:
+
+ path dirname basename
+ "/usr/lib" "/usr" "lib"
+ "/usr/" "/" "usr"
+ "usr" "." "usr"
+ "/" "/" "/"
+ "." "." "."
+ ".." "." ".."
+*/
+
+char*
+os_file_dirname(
+/*============*/
+ /* out, own: directory component of the
+ pathname */
+ char* path) /* in: pathname */
+{
+ char* dir;
+ int i, length, last_slash;
+
+ /* find the offset of the last slash */
+ length = ut_strlen(path);
+ for (i = length - 1; i >= 0 && path[i] != OS_FILE_PATH_SEPARATOR; i++);
+ last_slash = i;
+
+ if (last_slash < 0) {
+ /* no slash in the path, return "." */
+ return(ut_strdup((char*)"."));
+ }
+
+ /* ok, there is a slash */
+
+ if (last_slash == 0) {
+ /* last slash is the first char of the path */
+ return(ut_strdup((char*)"/"));
+ }
+
+ /* non-trivial directory component */
+ dir = ut_strdup(path);
+ dir[last_slash] = 0;
+
+ return(dir);
+}
+
+/********************************************************************
+Creates all missing subdirectories along the given path. */
+
+ibool
+os_file_create_subdirs_if_needed(
+/*=============================*/
+ /* out: TRUE if call succeeded
+ FALSE otherwise */
+ char* path) /* in: path name */
+{
+ char* subdir;
+ static char rootdir[2] = { OS_FILE_PATH_SEPARATOR, 0 };
+ ibool success, subdir_exists;
+ os_file_type_t type;
+
+ subdir = os_file_dirname(path);
+ if (0 == strcmp(subdir, rootdir) || 0 == strcmp(subdir, ".")) {
+ /* subdir is root or cwd, nothing to do */
+ ut_free(subdir);
+ return(TRUE);
+ }
+
+ /* test if subdir exists */
+ success = os_file_status(subdir, &subdir_exists, &type);
+ if (success && !subdir_exists) {
+ /* subdir does not exist, create it */
+ success = os_file_create_subdirs_if_needed(subdir);
+ if (!success) {
+ ut_free(subdir);
+ return(FALSE);
+ }
+ success = os_file_create_directory(subdir, FALSE);
+ }
+
+ ut_free(subdir);
+ return(success);
+}
+
/********************************************************************
Returns a pointer to the nth slot in the aio array. */
static
@@ -2430,7 +2627,7 @@ os_aio_get_array_no(
return(3);
} else {
- ut_a(0);
+ ut_error;
return(0);
}
@@ -2457,7 +2654,7 @@ os_aio_get_array_from_no(
return(os_aio_write_array);
} else {
- ut_a(0);
+ ut_error;
return(NULL);
}
@@ -3047,7 +3244,7 @@ os_aio_posix_handle(
if (sig != SIGRTMIN + 1 + array_no) {
- ut_a(0);
+ ut_error;
return(FALSE);
}
@@ -3312,7 +3509,7 @@ consecutive_loop:
slot->name, (ulong) slot->offset_high,
(ulong) slot->offset,
(ulong) total_len);
- ut_a(0);
+ ut_error;
}
/* Do a 'last millisecond' check that the page end
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index 89dad4f268f..5d26d12bf20 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -16,11 +16,12 @@ Created 10/4/1994 Heikki Tuuri
#include "log0recv.h"
#include "rem0cmp.h"
-ulint page_cur_short_succ = 0;
-
-ulint page_rnd = 976722341;
+static ulint page_rnd = 976722341;
#ifdef PAGE_CUR_ADAPT
+# ifdef UNIV_SEARCH_PERF_STAT
+ulint page_cur_short_succ = 0;
+# endif /* UNIV_SEARCH_PERF_STAT */
/********************************************************************
Tries a search shortcut based on the last insert. */
@@ -716,7 +717,7 @@ page_cur_parse_insert_rec(
buf_page_print(page);
- ut_a(0);
+ ut_error;
}
ut_memcpy(buf, rec_get_start(cursor_rec), mismatch_index);
diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c
index b7a85e79658..c64a7590b94 100644
--- a/innobase/page/page0page.c
+++ b/innobase/page/page0page.c
@@ -110,7 +110,7 @@ page_dir_find_owner_slot(
buf_page_print(page);
- ut_a(0);
+ ut_error;
}
i--;
@@ -441,7 +441,7 @@ page_copy_rec_list_end_no_locks(
(ulong)(rec - page),
(ulong)(page_cur_get_rec(&cur1) - page),
(ulong)(page_cur_get_rec(&cur2) - new_page));
- ut_a(0);
+ ut_error;
}
page_cur_move_to_next(&cur1);
diff --git a/innobase/pars/lexyy.c b/innobase/pars/lexyy.c
index 7c6711d2f97..f014200b2a6 100644
--- a/innobase/pars/lexyy.c
+++ b/innobase/pars/lexyy.c
@@ -627,7 +627,7 @@ Linux.
#define malloc(A) mem_alloc(A)
#define free(A) mem_free(A)
#define realloc(P, A) mem_realloc(P, A, __FILE__, __LINE__)
-#define exit(A) ut_a(0)
+#define exit(A) ut_error
#define YY_INPUT(buf, result, max_size) pars_get_lex_chars(buf, &result, max_size)
#define comment 1
diff --git a/innobase/pars/pars0pars.c b/innobase/pars/pars0pars.c
index 3e43b6ae262..5bbfca831f2 100644
--- a/innobase/pars/pars0pars.c
+++ b/innobase/pars/pars0pars.c
@@ -29,13 +29,14 @@ on 1/27/1998 */
#include "trx0trx.h"
#include "trx0roll.h"
#include "lock0lock.h"
-#include "odbc0odbc.h"
#include "eval0eval.h"
+#ifdef UNIV_SQL_DEBUG
/* If the following is set TRUE, the lexer will print the SQL string
as it tokenizes it */
ibool pars_print_lexed = FALSE;
+#endif /* UNIV_SQL_DEBUG */
/* Global variable used while parsing a single procedure or query : the code is
NOT re-entrant */
@@ -389,7 +390,7 @@ pars_resolve_exp_variables_and_types(
}
if (!node) {
- printf("PARSER ERROR: Unresolved identifier %s\n",
+ fprintf(stderr, "PARSER ERROR: Unresolved identifier %s\n",
sym_node->name);
}
@@ -522,25 +523,6 @@ pars_resolve_exp_list_columns(
}
/*************************************************************************
-Retrieves the stored procedure definition for a procedure name. */
-static
-void
-pars_retrieve_procedure_def(
-/*========================*/
- sym_node_t* sym_node) /* in: procedure name node */
-{
- ut_a(sym_node);
- ut_a(que_node_get_type(sym_node) == QUE_NODE_SYMBOL);
-
- sym_node->resolved = TRUE;
- sym_node->token_type = SYM_PROCEDURE_NAME;
-
- sym_node->procedure_def = dict_procedure_get((char*)sym_node->name,
- NULL);
- ut_a(sym_node->procedure_def);
-}
-
-/*************************************************************************
Retrieves the table definition for a table name id. */
static
void
@@ -1662,219 +1644,22 @@ pars_procedure_definition(
/*****************************************************************
Parses a stored procedure call, when this is not within another stored
-procedure, that is, the client issues a procedure call directly. */
+procedure, that is, the client issues a procedure call directly.
+In MySQL/InnoDB, stored InnoDB procedures are invoked via the
+parsed procedure tree, not via InnoDB SQL, so this function is not used. */
que_fork_t*
pars_stored_procedure_call(
/*=======================*/
/* out: query graph */
- sym_node_t* sym_node) /* in: stored procedure name */
+ sym_node_t* sym_node __attribute__((unused)))
+ /* in: stored procedure name */
{
- call_node_t* node;
- que_fork_t* fork;
- que_thr_t* thr;
- mem_heap_t* heap;
-
- heap = pars_sym_tab_global->heap;
-
- fork = que_fork_create(NULL, NULL, QUE_FORK_PROCEDURE_CALL, heap);
- fork->trx = NULL;
-
- thr = que_thr_create(fork, heap);
-
- node = mem_heap_alloc(heap, sizeof(call_node_t));
-
- thr->child = node;
-
- node->common.type = QUE_NODE_CALL;
- node->common.parent = thr;
-
- sym_node->token_type = SYM_PROCEDURE_NAME;
-
- pars_retrieve_procedure_def(sym_node);
-
- node->procedure_def = sym_node->procedure_def;
- node->proc_name = sym_node;
-
- node->sym_tab = pars_sym_tab_global;
-
- pars_sym_tab_global->query_graph = fork;
-
- return(fork);
-}
-
-/*****************************************************************
-Writes info about query parameter markers (denoted with '?' in ODBC) into a
-buffer. */
-
-ulint
-pars_write_query_param_info(
-/*========================*/
- /* out: number of bytes used for info in buf */
- byte* buf, /* in: buffer which must be big enough */
- que_fork_t* graph) /* in: parsed query graph */
-{
- que_thr_t* thr;
- call_node_t* call_node;
- dict_proc_t* procedure_def;
- que_t* stored_graph;
- proc_node_t* proc_node;
- sym_node_t* param;
- ulint n_params;
- ibool is_input;
-
- /* We currently support parameter markers only in stored procedure
- calls, and there ALL procedure parameters must be marked with '?':
- no literal values are allowed */
-
- thr = UT_LIST_GET_FIRST(graph->thrs);
-
- n_params = 0;
-
- if (que_node_get_type(thr->child) == QUE_NODE_CALL) {
- call_node = thr->child;
-
- procedure_def = call_node->procedure_def;
-
- stored_graph = dict_procedure_reserve_parsed_copy(
- procedure_def);
- proc_node = que_fork_get_child(stored_graph);
-
- param = proc_node->param_list;
-
- while (param) {
- if (param->param_type == PARS_INPUT) {
- is_input = TRUE;
- } else {
- is_input = FALSE;
- }
-
- mach_write_to_1(buf + 4 + n_params, is_input);
-
- n_params++;
-
- param = que_node_get_next(param);
- }
-
- dict_procedure_release_parsed_copy(stored_graph);
- }
-
- mach_write_to_4(buf, n_params);
-
- return(4 + n_params);
+ ut_error;
+ return(NULL);
}
/*****************************************************************
-Reads stored procedure input parameter values from a buffer. */
-
-void
-pars_proc_read_input_params_from_buf(
-/*=================================*/
- que_t* graph, /* in: query graph which contains a stored procedure */
- byte* buf) /* in: buffer */
-{
- que_thr_t* thr;
- proc_node_t* proc_node;
- sym_node_t* param;
- byte* ptr;
- ulint len;
- lint odbc_len;
-
- ut_ad(graph->fork_type == QUE_FORK_PROCEDURE);
-
- thr = UT_LIST_GET_FIRST(graph->thrs);
-
- proc_node = thr->child;
-
- ptr = buf;
-
- param = proc_node->param_list;
-
- while (param) {
- if (param->param_type == PARS_INPUT) {
- odbc_len = (lint)mach_read_from_4(ptr);
-
- ptr += 4;
-
- if (odbc_len == SQL_NULL_DATA) {
- len = UNIV_SQL_NULL;
- } else {
- len = (ulint)odbc_len;
- }
-
- eval_node_copy_and_alloc_val(param, ptr, len);
-
- if (len != UNIV_SQL_NULL) {
- ptr += len;
- }
- }
-
- param = que_node_get_next(param);
- }
-
- ut_ad(ptr - buf < ODBC_DATAGRAM_SIZE);
-}
-
-/*****************************************************************
-Writes stored procedure output parameter values to a buffer. */
-
-ulint
-pars_proc_write_output_params_to_buf(
-/*=================================*/
- /* out: bytes used in buf */
- byte* buf, /* in: buffer which must be big enough */
- que_t* graph) /* in: query graph which contains a stored procedure */
-{
- que_thr_t* thr;
- proc_node_t* proc_node;
- sym_node_t* param;
- dfield_t* dfield;
- byte* ptr;
- ulint len;
- lint odbc_len;
-
- ut_ad(graph->fork_type == QUE_FORK_PROCEDURE);
-
- thr = UT_LIST_GET_FIRST(graph->thrs);
-
- proc_node = thr->child;
-
- ptr = buf;
-
- param = proc_node->param_list;
-
- while (param) {
- if (param->param_type == PARS_OUTPUT) {
- dfield = que_node_get_val(param);
-
- len = dfield_get_len(dfield);
-
- if (len == UNIV_SQL_NULL) {
- odbc_len = SQL_NULL_DATA;
- } else {
- odbc_len = (lint)len;
- }
-
- mach_write_to_4(ptr, (ulint)odbc_len);
-
- ptr += 4;
-
- if (len != UNIV_SQL_NULL) {
- ut_memcpy(ptr, dfield_get_data(dfield), len);
-
- ptr += len;
- }
- }
-
- param = que_node_get_next(param);
- }
-
- ut_ad(ptr - buf < ODBC_DATAGRAM_SIZE);
-
- return((ulint)(ptr - buf));
-}
-
-/*****************************************************************
Retrieves characters to the lexical analyzer. */
void
@@ -1886,13 +1671,12 @@ pars_get_lex_chars(
in the buffer */
{
int len;
- char print_buf[16];
len = pars_sym_tab_global->string_len
- pars_sym_tab_global->next_char_pos;
if (len == 0) {
#ifdef YYDEBUG
- /* printf("SQL string ends\n"); */
+ /* fputs("SQL string ends\n", stderr); */
#endif
*result = 0;
@@ -1903,18 +1687,18 @@ pars_get_lex_chars(
len = max_size;
}
+#ifdef UNIV_SQL_DEBUG
if (pars_print_lexed) {
if (len >= 5) {
len = 5;
}
-
- ut_memcpy(print_buf, pars_sym_tab_global->sql_string +
- pars_sym_tab_global->next_char_pos, len);
- print_buf[len] = '\0';
-
- printf("%s", print_buf);
+
+ fwrite(pars_sym_tab_global->sql_string +
+ pars_sym_tab_global->next_char_pos,
+ 1, len, stderr);
}
+#endif /* UNIV_SQL_DEBUG */
ut_memcpy(buf, pars_sym_tab_global->sql_string +
pars_sym_tab_global->next_char_pos, len);
@@ -1944,7 +1728,7 @@ yyerror(
{
ut_ad(s);
- printf("PARSER ERROR: Syntax error in SQL string\n");
+ fputs("PARSER ERROR: Syntax error in SQL string\n", stderr);
ut_error;
}
@@ -1968,10 +1752,10 @@ pars_sql(
heap = mem_heap_create(256);
+#ifdef UNIV_SYNC_DEBUG
/* Currently, the parser is not reentrant: */
-
ut_ad(mutex_own(&(dict_sys->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
pars_sym_tab_global = sym_tab_create(heap);
len = ut_strlen(str);
@@ -1996,7 +1780,7 @@ pars_sql(
graph->sym_tab = pars_sym_tab_global;
- /* printf("SQL graph size %lu\n", mem_heap_get_size(heap)); */
+ /* fprintf(stderr, "SQL graph size %lu\n", mem_heap_get_size(heap)); */
return(graph);
}
diff --git a/innobase/que/que0que.c b/innobase/que/que0que.c
index 40483988c12..b2608b6d175 100644
--- a/innobase/que/que0que.c
+++ b/innobase/que/que0que.c
@@ -25,7 +25,6 @@ Created 5/27/1996 Heikki Tuuri
#include "log0log.h"
#include "eval0proc.h"
#include "eval0eval.h"
-#include "odbc0odbc.h"
#define QUE_PARALLELIZE_LIMIT (64 * 256 * 256 * 256)
#define QUE_ROUND_ROBIN_LIMIT (64 * 256 * 256 * 256)
@@ -83,7 +82,9 @@ que_graph_publish(
que_t* graph, /* in: graph */
sess_t* sess) /* in: session */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
UT_LIST_ADD_LAST(graphs, sess->graphs, graph);
}
@@ -190,7 +191,9 @@ que_thr_end_wait(
{
ibool was_active;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(thr);
ut_ad((thr->state == QUE_THR_LOCK_WAIT)
|| (thr->state == QUE_THR_PROCEDURE_WAIT)
@@ -229,7 +232,9 @@ que_thr_end_wait_no_next_thr(
ut_a(thr->state == QUE_THR_LOCK_WAIT); /* In MySQL this is the
only possible state here */
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(thr);
ut_ad((thr->state == QUE_THR_LOCK_WAIT)
|| (thr->state == QUE_THR_PROCEDURE_WAIT)
@@ -279,15 +284,9 @@ que_fork_start_command(
QUE_THR_RUNNING state, or NULL; the query
thread should be executed by que_run_threads
by the caller */
- que_fork_t* fork, /* in: a query fork */
- ulint command,/* in: command SESS_COMM_FETCH_NEXT, ... */
- ulint param) /* in: possible parameter to the command */
+ que_fork_t* fork) /* in: a query fork */
{
que_thr_t* thr;
-
- /* Set the command parameters in the fork root */
- fork->command = command;
- fork->param = param;
fork->state = QUE_FORK_ACTIVE;
@@ -370,7 +369,9 @@ que_fork_error_handle(
{
que_thr_t* thr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(trx->sess->state == SESS_ERROR);
ut_ad(UT_LIST_GET_LEN(trx->reply_signals) == 0);
ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
@@ -484,7 +485,7 @@ que_graph_free_recursive(
"que_thr struct appears corrupt; magic n %lu\n",
(unsigned long) thr->magic_n);
mem_analyze_corruption((byte*)thr);
- ut_a(0);
+ ut_error;
}
thr->magic_n = QUE_THR_MAGIC_FREED;
@@ -596,7 +597,7 @@ que_graph_free_recursive(
"que_node struct appears corrupt; type %lu\n",
(unsigned long) que_node_get_type(node));
mem_analyze_corruption((byte*)node);
- ut_a(0);
+ ut_error;
}
}
@@ -640,7 +641,9 @@ que_graph_try_free(
{
sess_t* sess;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
sess = (graph->trx)->sess;
@@ -665,50 +668,21 @@ does nothing! */
void
que_thr_handle_error(
/*=================*/
- que_thr_t* thr, /* in: query thread */
- ulint err_no, /* in: error number */
- byte* err_str,/* in, own: error string or NULL; NOTE: the
+ que_thr_t* thr __attribute__((unused)),
+ /* in: query thread */
+ ulint err_no __attribute__((unused)),
+ /* in: error number */
+ byte* err_str __attribute__((unused)),
+ /* in, own: error string or NULL; NOTE: the
function will take care of freeing of the
string! */
- ulint err_len)/* in: error string length */
+ ulint err_len __attribute__((unused)))
+ /* in: error string length */
{
- UT_NOT_USED(thr);
- UT_NOT_USED(err_no);
- UT_NOT_USED(err_str);
- UT_NOT_USED(err_len);
-
/* Does nothing */
}
/********************************************************************
-Builds a command completed-message to the client. */
-static
-ulint
-que_build_srv_msg(
-/*==============*/
- /* out: message data length */
- byte* buf, /* in: message buffer */
- que_fork_t* fork, /* in: query graph where execution completed */
- sess_t* sess) /* in: session */
-{
- ulint len;
-
- /* Currently, we only support stored procedures: */
- ut_ad(fork->fork_type == QUE_FORK_PROCEDURE);
-
- if (sess->state == SESS_ERROR) {
-
- return(0);
- }
-
- sess_srv_msg_init(sess, buf, SESS_SRV_SUCCESS);
-
- len = pars_proc_write_output_params_to_buf(buf + SESS_SRV_MSG_DATA,
- fork);
- return(len);
-}
-
-/********************************************************************
Performs an execution step on a thr node. */
static
que_thr_t*
@@ -804,10 +778,6 @@ que_thr_dec_refer_count(
que_fork_t* fork;
trx_t* trx;
sess_t* sess;
- ibool send_srv_msg = FALSE;
- ibool release_stored_proc = FALSE;
- ulint msg_len = 0;
- byte msg_buf[ODBC_DATAGRAM_SIZE];
ulint fork_type;
ibool stopped;
@@ -828,8 +798,8 @@ que_thr_dec_refer_count(
already canceled before we came here: continue
running the thread */
- /* printf(
- "!!!!!!!!!! Wait already ended: continue thr\n"); */
+ /* fputs("!!!!!!!! Wait already ended: continue thr\n",
+ stderr); */
if (next_thr && *next_thr == NULL) {
*next_thr = thr;
@@ -882,40 +852,13 @@ que_thr_dec_refer_count(
} else if (fork_type == QUE_FORK_MYSQL_INTERFACE) {
/* Do nothing */
- } else if (fork->common.parent == NULL
- && fork->caller == NULL
- && UT_LIST_GET_LEN(trx->signals) == 0) {
-
- ut_a(0); /* not used in MySQL */
-
- /* Reply to the client */
-
- /* que_thr_add_update_info(thr); */
-
- fork->state = QUE_FORK_COMMAND_WAIT;
-
- msg_len = que_build_srv_msg(msg_buf, fork, sess);
-
- send_srv_msg = TRUE;
-
- if (fork->fork_type == QUE_FORK_PROCEDURE) {
-
- release_stored_proc = TRUE;
- }
-
- ut_ad(trx->graph == fork);
-
- trx->graph = NULL;
} else {
- /* Subprocedure calls not implemented yet */
- ut_a(0);
+ ut_error; /* not used in MySQL */
}
}
if (UT_LIST_GET_LEN(trx->signals) > 0 && trx->n_active_thrs == 0) {
- ut_ad(!send_srv_msg);
-
/* If the trx is signaled and its query thread count drops to
zero, then we start processing a signal; from it we may get
a new query thread to run */
@@ -929,26 +872,6 @@ que_thr_dec_refer_count(
}
mutex_exit(&kernel_mutex);
-
- if (send_srv_msg) {
- /* Note that, as we do not own the kernel mutex at this point,
- and neither do we own it all the time when doing the actual
- communication operation within the next function, it is
- possible that the messages will not get delivered in the right
- sequential order. This is possible if the client communicates
- an extra message to the server while the message below is still
- undelivered. But then the client should notice that there
- is an error in the order numbers of the messages. */
-
- sess_command_completed_message(sess, msg_buf, msg_len);
- }
-
- if (release_stored_proc) {
-
- /* Return the stored procedure graph to the dictionary cache */
-
- dict_procedure_release_parsed_copy(fork);
- }
}
/**************************************************************************
@@ -966,7 +889,9 @@ que_thr_stop(
que_t* graph;
ibool ret = TRUE;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
graph = thr->graph;
trx = graph->trx;
@@ -1063,7 +988,7 @@ que_thr_move_to_run_state_for_mysql(
mem_analyze_corruption((byte*)thr);
- ut_a(0);
+ ut_error;
}
if (!thr->is_active) {
@@ -1100,7 +1025,7 @@ que_thr_stop_for_mysql_no_error(
mem_analyze_corruption((byte*)thr);
- ut_a(0);
+ ut_error;
}
thr->state = QUE_THR_COMPLETED;
@@ -1111,69 +1036,67 @@ que_thr_stop_for_mysql_no_error(
trx->n_active_thrs--;
}
+#ifdef UNIV_DEBUG
/**************************************************************************
Prints info of an SQL query graph node. */
-
+static
void
que_node_print_info(
/*================*/
que_node_t* node) /* in: query graph node */
{
- ulint type;
- char* str;
- ulint addr;
+ ulint type;
+ const char* str;
type = que_node_get_type(node);
- addr = (ulint)node;
-
if (type == QUE_NODE_SELECT) {
- str = (char *) "SELECT";
+ str = "SELECT";
} else if (type == QUE_NODE_INSERT) {
- str = (char *) "INSERT";
+ str = "INSERT";
} else if (type == QUE_NODE_UPDATE) {
- str = (char *) "UPDATE";
+ str = "UPDATE";
} else if (type == QUE_NODE_WHILE) {
- str = (char *) "WHILE";
+ str = "WHILE";
} else if (type == QUE_NODE_ASSIGNMENT) {
- str = (char *) "ASSIGNMENT";
+ str = "ASSIGNMENT";
} else if (type == QUE_NODE_IF) {
- str = (char *) "IF";
+ str = "IF";
} else if (type == QUE_NODE_FETCH) {
- str = (char *) "FETCH";
+ str = "FETCH";
} else if (type == QUE_NODE_OPEN) {
- str = (char *) "OPEN";
+ str = "OPEN";
} else if (type == QUE_NODE_PROC) {
- str = (char *) "STORED PROCEDURE";
+ str = "STORED PROCEDURE";
} else if (type == QUE_NODE_FUNC) {
- str = (char *) "FUNCTION";
+ str = "FUNCTION";
} else if (type == QUE_NODE_LOCK) {
- str = (char *) "LOCK";
+ str = "LOCK";
} else if (type == QUE_NODE_THR) {
- str = (char *) "QUERY THREAD";
+ str = "QUERY THREAD";
} else if (type == QUE_NODE_COMMIT) {
- str = (char *) "COMMIT";
+ str = "COMMIT";
} else if (type == QUE_NODE_UNDO) {
- str = (char *) "UNDO ROW";
+ str = "UNDO ROW";
} else if (type == QUE_NODE_PURGE) {
- str = (char *) "PURGE ROW";
+ str = "PURGE ROW";
} else if (type == QUE_NODE_ROLLBACK) {
- str = (char *) "ROLLBACK";
+ str = "ROLLBACK";
} else if (type == QUE_NODE_CREATE_TABLE) {
- str = (char *) "CREATE TABLE";
+ str = "CREATE TABLE";
} else if (type == QUE_NODE_CREATE_INDEX) {
- str = (char *) "CREATE INDEX";
+ str = "CREATE INDEX";
} else if (type == QUE_NODE_FOR) {
- str = (char *) "FOR LOOP";
+ str = "FOR LOOP";
} else if (type == QUE_NODE_RETURN) {
- str = (char *) "RETURN";
+ str = "RETURN";
} else {
- str = (char *) "UNKNOWN NODE TYPE";
+ str = "UNKNOWN NODE TYPE";
}
- printf("Node type %lu: %s, address %lx\n", (unsigned long) type, str,
- (unsigned long) addr);
+ fprintf(stderr, "Node type %lu: %s, address %p\n", (ulong) type, str, node);
}
+#endif /* UNIV_DEBUG */
/**************************************************************************
Performs an execution step on a query thread. */
@@ -1202,7 +1125,7 @@ que_thr_step(
#ifdef UNIV_DEBUG
if (que_trace_on) {
- printf("To execute: ");
+ fputs("To execute: ", stderr);
que_node_print_info(node);
}
#endif
@@ -1299,7 +1222,9 @@ que_run_threads(
ulint loop_count;
ut_ad(thr->state == QUE_THR_RUNNING);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
/* cumul_resource counts how much resources the OS thread (NOT the
query thread) has spent in this function */
diff --git a/innobase/read/read0read.c b/innobase/read/read0read.c
index 4a8aaee39ca..889612deef4 100644
--- a/innobase/read/read0read.c
+++ b/innobase/read/read0read.c
@@ -54,9 +54,10 @@ read_view_oldest_copy_or_open_new(
ulint insert_done = 0;
ulint n;
ulint i;
-
- ut_ad(mutex_own(&kernel_mutex));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
old_view = UT_LIST_GET_LAST(trx_sys->view_list);
if (old_view == NULL) {
@@ -132,9 +133,9 @@ read_view_open_now(
read_view_t* view;
trx_t* trx;
ulint n;
-
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
-
+#endif /* UNIV_SYNC_DEBUG */
view = read_view_create_low(UT_LIST_GET_LEN(trx_sys->trx_list), heap);
view->creator = cr_trx;
@@ -195,8 +196,9 @@ read_view_close(
/*============*/
read_view_t* view) /* in: read view */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
-
+#endif /* UNIV_SYNC_DEBUG */
UT_LIST_REMOVE(view_list, trx_sys->view_list, view);
}
diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c
index fb8732f35be..254ebeec8c9 100644
--- a/innobase/rem/rem0cmp.c
+++ b/innobase/rem/rem0cmp.c
@@ -283,7 +283,7 @@ cmp_whole_field(
fprintf(stderr,
"InnoDB: unknown type number %lu\n",
(ulong) data_type);
- ut_a(0);
+ ut_error;
}
return(0);
diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c
index 5a3996c9dce..3d0b997db85 100644
--- a/innobase/rem/rem0rec.c
+++ b/innobase/rem/rem0rec.c
@@ -108,12 +108,12 @@ rec_get_nth_field(
if (n > 1024) {
fprintf(stderr, "Error: trying to access field %lu in rec\n",
(ulong) n);
- ut_a(0);
+ ut_error;
}
if (rec == NULL) {
fprintf(stderr, "Error: rec is NULL pointer\n");
- ut_a(0);
+ ut_error;
}
if (rec_get_1byte_offs_flag(rec)) {
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 5fef07683af..fc1f7a19d53 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -80,9 +80,9 @@ ins_node_create(
node->trx_id = ut_dulint_zero;
node->entry_sys_heap = mem_heap_create(128);
-
- node->magic_n = INS_NODE_MAGIC_N;
-
+#ifdef UNIV_DEBUG
+ node->magic_n = INS_NODE_MAGIC_N;
+#endif /* UNIV_DEBUG */
return(node);
}
@@ -194,6 +194,7 @@ ins_node_set_new_row(
ins_node_t* node, /* in: insert node */
dtuple_t* row) /* in: new row (or first row) for the node */
{
+ ut_ad(node->magic_n == INS_NODE_MAGIC_N);
node->state = INS_NODE_SET_IX_LOCK;
node->index = NULL;
node->entry = NULL;
@@ -855,7 +856,7 @@ row_ins_foreign_check_on_constraint(
"InnoDB: Make a detailed bug report and send it\n");
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
- ut_a(0);
+ ut_error;
*/
err = DB_SUCCESS;
@@ -1031,8 +1032,10 @@ row_ins_check_foreign_constraint(
mtr_t mtr;
run_again:
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_SHARED));
-
+#endif /* UNIV_SYNC_DEBUG */
+
err = DB_SUCCESS;
if (thr_get_trx(thr)->check_foreigns == FALSE) {
@@ -2040,6 +2043,7 @@ row_ins(
ulint err;
ut_ad(node && thr);
+ ut_ad(node->magic_n == INS_NODE_MAGIC_N);
if (node->state == INS_NODE_ALLOC_ROW_ID) {
@@ -2104,7 +2108,7 @@ row_ins_step(
trx_start_if_not_started(trx);
node = thr->run_node;
-
+ ut_ad(node->magic_n == INS_NODE_MAGIC_N);
ut_ad(que_node_get_type(node) == QUE_NODE_INSERT);
parent = que_node_get_parent(node);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 626382398b7..49e5aeac2e4 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -287,7 +287,7 @@ handle_new_error:
} else {
fprintf(stderr, "InnoDB: unknown error code %lu\n",
(ulong) err);
- ut_a(0);
+ ut_error;
}
if (trx->error_state != DB_SUCCESS) {
@@ -402,7 +402,7 @@ row_prebuilt_free(
mem_analyze_corruption((byte*)prebuilt);
- ut_a(0);
+ ut_error;
}
prebuilt->magic_n = ROW_PREBUILT_FREED;
@@ -450,7 +450,7 @@ row_prebuilt_free(
mem_analyze_corruption(
prebuilt->fetch_cache[i]);
- ut_a(0);
+ ut_error;
}
mem_free((prebuilt->fetch_cache[i]) - 4);
@@ -482,7 +482,7 @@ row_update_prebuilt_trx(
mem_analyze_corruption((byte*)trx);
- ut_a(0);
+ ut_error;
}
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
@@ -493,7 +493,7 @@ row_update_prebuilt_trx(
mem_analyze_corruption((byte*)prebuilt);
- ut_a(0);
+ ut_error;
}
prebuilt->trx = trx;
@@ -720,7 +720,7 @@ row_insert_for_mysql(
mem_analyze_corruption((byte*)prebuilt);
- ut_a(0);
+ ut_error;
}
if (srv_created_new_raw || srv_force_recovery) {
@@ -936,7 +936,7 @@ row_update_for_mysql(
mem_analyze_corruption((byte*)prebuilt);
- ut_a(0);
+ ut_error;
}
if (srv_created_new_raw || srv_force_recovery) {
@@ -1289,9 +1289,11 @@ row_create_table_for_mysql(
ulint err;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
- ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
if (srv_created_new_raw) {
fprintf(stderr,
@@ -1424,8 +1426,7 @@ row_create_table_for_mysql(
thr = pars_complete_graph_for_exec(node, trx, heap);
- ut_a(thr == que_fork_start_command(que_node_get_parent(thr),
- SESS_COMM_EXECUTE, 0));
+ ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
que_run_threads(thr);
err = trx->error_state;
@@ -1496,8 +1497,10 @@ row_create_index_for_mysql(
ulint err;
ulint i, j;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
trx->op_info = (char *) "creating index";
@@ -1552,8 +1555,7 @@ row_create_index_for_mysql(
thr = pars_complete_graph_for_exec(node, trx, heap);
- ut_a(thr == que_fork_start_command(que_node_get_parent(thr),
- SESS_COMM_EXECUTE, 0));
+ ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
que_run_threads(thr);
err = trx->error_state;
@@ -1604,8 +1606,10 @@ row_table_add_foreign_constraints(
ulint keywordlen;
ulint err;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(sql_string);
trx->op_info = (char *) "adding foreign keys";
@@ -1776,7 +1780,9 @@ row_get_background_drop_list_len_low(void)
/*======================================*/
/* out: how many tables in list */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (!row_mysql_drop_list_inited) {
@@ -1928,7 +1934,7 @@ row_discard_tablespace_for_mysql(
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
- ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
+ ut_a(thr = que_fork_start_command(graph));
que_run_threads(thr);
@@ -2255,8 +2261,10 @@ row_drop_table_for_mysql(
locked_dictionary = TRUE;
}
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
graph = pars_sql(buf);
@@ -2356,7 +2364,7 @@ row_drop_table_for_mysql(
trx->dict_operation = TRUE;
trx->table_id = table->id;
- ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
+ ut_a(thr = que_fork_start_command(graph));
que_run_threads(thr);
@@ -2369,7 +2377,7 @@ row_drop_table_for_mysql(
row_mysql_handle_errors(&err, trx, thr, NULL);
- ut_a(0);
+ ut_error;
} else {
space_id = table->space;
dict_table_remove_from_cache(table);
@@ -2786,7 +2794,7 @@ row_rename_table_for_mysql(
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
- ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
+ ut_a(thr = que_fork_start_command(graph));
que_run_threads(thr);
diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c
index d5895f20461..a409b64f8e4 100644
--- a/innobase/row/row0purge.c
+++ b/innobase/row/row0purge.c
@@ -140,7 +140,7 @@ row_purge_remove_clust_if_poss_low(
} else if (err == DB_OUT_OF_FILE_SPACE) {
success = FALSE;
} else {
- ut_a(0);
+ ut_error;
}
}
@@ -266,7 +266,7 @@ row_purge_remove_sec_if_poss_low(
} else if (err == DB_OUT_OF_FILE_SPACE) {
success = FALSE;
} else {
- ut_a(0);
+ ut_error;
}
}
}
@@ -447,8 +447,10 @@ skip_secondaries:
data_field = buf_page_get(0, page_no, RW_X_LATCH, &mtr)
+ offset + internal_offset;
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(buf_frame_align(data_field),
SYNC_TRX_UNDO_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
data_field_len = ufield->new_val.len;
diff --git a/innobase/row/row0row.c b/innobase/row/row0row.c
index b5d676a936a..6820cb5bccd 100644
--- a/innobase/row/row0row.c
+++ b/innobase/row/row0row.c
@@ -406,7 +406,7 @@ row_build_row_ref_in_tuple(
if (!table) {
fprintf(stderr, "InnoDB: table %s for index %s not found\n",
index->table_name, index->name);
- ut_a(0);
+ ut_error;
}
clust_index = dict_table_get_first_index(table);
@@ -415,7 +415,7 @@ row_build_row_ref_in_tuple(
fprintf(stderr,
"InnoDB: clust index for table %s for index %s not found\n",
index->table_name, index->name);
- ut_a(0);
+ ut_error;
}
ref_len = dict_index_get_n_unique(clust_index);
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index b32f0b204b3..4f70cea2058 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -930,7 +930,9 @@ row_sel_try_search_shortcut(
ut_ad(node->read_view);
ut_ad(plan->unique_search);
ut_ad(!plan->must_get_clust);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
row_sel_open_pcur(node, plan, TRUE, mtr);
@@ -2080,7 +2082,7 @@ row_sel_store_row_id_to_prebuilt(
(ulong) len, index->table_name, index->name,
(ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID),
err_buf);
- ut_a(0);
+ ut_error;
}
ut_memcpy(prebuilt->row_id, data, len);
@@ -2770,7 +2772,7 @@ row_search_for_mysql(
mem_analyze_corruption((byte*)prebuilt);
- ut_a(0);
+ ut_error;
}
if (trx->n_mysql_tables_in_use == 0) {
@@ -2831,7 +2833,7 @@ row_search_for_mysql(
if (direction != prebuilt->fetch_direction) {
if (prebuilt->n_fetch_cached > 0) {
- ut_a(0);
+ ut_error;
/* TODO: scrollable cursor: restore cursor to
the place of the latest returned row,
or better: prevent caching for a scroll
diff --git a/innobase/row/row0undo.c b/innobase/row/row0undo.c
index f223bb5eed5..613d0a3b890 100644
--- a/innobase/row/row0undo.c
+++ b/innobase/row/row0undo.c
@@ -334,7 +334,7 @@ row_undo_step(
exit(1);
}
- ut_a(0);
+ ut_error;
return(NULL);
}
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index b9e9b8c15c9..f8739b65c2f 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -77,8 +77,8 @@ index record. This is only used in foreign key checks and we can assume
that index does not contain column prefixes. */
static
ibool
-row_upd_changes_first_fields(
-/*=========================*/
+row_upd_changes_first_fields_binary(
+/*================================*/
/* out: TRUE if changes */
dtuple_t* entry, /* in: old value of index entry */
dict_index_t* index, /* in: index of entry */
@@ -196,7 +196,7 @@ row_upd_check_references_constraints(
if (foreign->referenced_index == index
&& (node->is_delete
- || row_upd_changes_first_fields(entry, index,
+ || row_upd_changes_first_fields_binary(entry, index,
node->update, foreign->n_fields))) {
if (foreign->foreign_table == NULL) {
@@ -287,7 +287,9 @@ upd_node_create(
node->select = NULL;
node->heap = mem_heap_create(128);
- node->magic_n = UPD_NODE_MAGIC_N;
+#ifdef UNIV_DEBUG
+ node->magic_n = UPD_NODE_MAGIC_N;
+#endif /* UNIV_DEBUG */
node->cmpl_info = 0;
@@ -1048,8 +1050,8 @@ index record. This is only used in foreign key checks and we can assume
that index does not contain column prefixes. */
static
ibool
-row_upd_changes_first_fields(
-/*=========================*/
+row_upd_changes_first_fields_binary(
+/*================================*/
/* out: TRUE if changes */
dtuple_t* entry, /* in: index entry */
dict_index_t* index, /* in: index of entry */
@@ -1074,15 +1076,16 @@ row_upd_changes_first_fields(
col = dict_field_get_col(ind_field);
col_pos = dict_col_get_clust_pos(col);
+ ut_a(ind_field->prefix_len == 0);
+
for (j = 0; j < n_upd_fields; j++) {
upd_field = upd_get_nth_field(update, j);
if (col_pos == upd_field->field_no
- && (ind_field->prefix_len > 0
- || 0 != cmp_dfield_dfield(
+ && !dfield_datas_are_binary_equal(
dtuple_get_nth_field(entry, i),
- &(upd_field->new_val)))) {
+ &(upd_field->new_val))) {
return(TRUE);
}
}
@@ -1804,6 +1807,7 @@ row_upd_step(
trx_start_if_not_started(trx);
node = thr->run_node;
+ ut_ad(node->magic_n == UPD_NODE_MAGIC_N);
sel_node = node->select;
@@ -1923,6 +1927,7 @@ row_upd_in_place_in_select(
node = que_node_get_parent(sel_node);
+ ut_ad(node->magic_n == UPD_NODE_MAGIC_N);
ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE);
pcur = node->pcur;
diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c
index fca56389e45..bc17ede89e3 100644
--- a/innobase/row/row0vers.c
+++ b/innobase/row/row0vers.c
@@ -60,8 +60,10 @@ row_vers_impl_x_locked_off_kernel(
ulint err;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
mutex_exit(&kernel_mutex);
@@ -254,7 +256,9 @@ row_vers_must_preserve_del_marked(
mtr_t* mtr) /* in: mtr holding the latch on the clustered index
record; it will also hold the latch on purge_view */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
mtr_s_lock(&(purge_sys->latch), mtr);
@@ -302,7 +306,9 @@ row_vers_old_has_index_entry(
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains(mtr, buf_block_align(rec),
MTR_MEMO_PAGE_S_FIX));
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
mtr_s_lock(&(purge_sys->latch), mtr);
clust_index = dict_table_get_first_index(index->table);
@@ -411,7 +417,9 @@ row_vers_build_for_consistent_read(
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains(mtr, buf_block_align(rec),
MTR_MEMO_PAGE_S_FIX));
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(!read_view_sees_trx_id(view, row_get_rec_trx_id(rec, index)));
rw_lock_s_lock(&(purge_sys->latch));
diff --git a/innobase/srv/srv0que.c b/innobase/srv/srv0que.c
index 4d36adfefa4..ac8bd7d0e65 100644
--- a/innobase/srv/srv0que.c
+++ b/innobase/srv/srv0que.c
@@ -83,7 +83,9 @@ srv_que_task_enqueue_low(
{
ut_ad(thr);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
UT_LIST_ADD_LAST(queue, srv_sys->tasks, thr);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index e9ea4155e0d..838e63b3e25 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -34,12 +34,9 @@ Created 10/8/1995 Heikki Tuuri
#include "sync0sync.h"
#include "sync0ipm.h"
#include "thr0loc.h"
-#include "com0com.h"
-#include "com0shm.h"
#include "que0que.h"
#include "srv0que.h"
#include "log0recv.h"
-#include "odbc0odbc.h"
#include "pars0pars.h"
#include "usr0sess.h"
#include "lock0lock.h"
@@ -253,9 +250,6 @@ ibool srv_use_adaptive_hash_indexes = TRUE;
ulint srv_n_spin_wait_rounds = 20;
ulint srv_spin_wait_delay = 5;
ibool srv_priority_boost = TRUE;
-char srv_endpoint_name[COM_MAX_ADDR_LEN];
-ulint srv_n_com_threads = ULINT_MAX;
-ulint srv_n_worker_threads = ULINT_MAX;
ibool srv_print_thread_releases = FALSE;
ibool srv_print_lock_waits = FALSE;
@@ -263,14 +257,14 @@ ibool srv_print_buf_io = FALSE;
ibool srv_print_log_io = FALSE;
ibool srv_print_latch_waits = FALSE;
-ulint srv_n_rows_inserted = 0;
-ulint srv_n_rows_updated = 0;
-ulint srv_n_rows_deleted = 0;
-ulint srv_n_rows_read = 0;
-ulint srv_n_rows_inserted_old = 0;
-ulint srv_n_rows_updated_old = 0;
-ulint srv_n_rows_deleted_old = 0;
-ulint srv_n_rows_read_old = 0;
+ulint srv_n_rows_inserted = 0;
+ulint srv_n_rows_updated = 0;
+ulint srv_n_rows_deleted = 0;
+ulint srv_n_rows_read = 0;
+static ulint srv_n_rows_inserted_old = 0;
+static ulint srv_n_rows_updated_old = 0;
+static ulint srv_n_rows_deleted_old = 0;
+static ulint srv_n_rows_read_old = 0;
/*
Set the following to 0 if you want InnoDB to write messages on
@@ -630,7 +624,9 @@ srv_suspend_thread(void)
ulint slot_no;
ulint type;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
@@ -681,7 +677,9 @@ srv_release_threads(
ut_ad(type >= SRV_WORKER);
ut_ad(type <= SRV_MASTER);
ut_ad(n > 0);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
for (i = 0; i < OS_THREAD_MAX_N; i++) {
@@ -1185,7 +1183,9 @@ srv_table_reserve_slot_for_mysql(void)
srv_slot_t* slot;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
i = 0;
slot = srv_mysql_table + i;
@@ -1215,7 +1215,7 @@ srv_table_reserve_slot_for_mysql(void)
(ulong) difftime(ut_time(), slot->suspend_time));
}
- ut_a(0);
+ ut_error;
}
slot = srv_mysql_table + i;
@@ -1250,7 +1250,9 @@ srv_suspend_mysql_thread(
ibool had_dict_lock = FALSE;
ibool was_declared_inside_innodb = FALSE;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
trx = thr_get_trx(thr);
@@ -1369,7 +1371,9 @@ srv_release_mysql_thread_if_suspended(
srv_slot_t* slot;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
for (i = 0; i < OS_THREAD_MAX_N; i++) {
@@ -1465,6 +1469,13 @@ srv_sprintf_innodb_monitor(
buf = buf + strlen(buf);
ut_a(buf < buf_end + 1500);
+ /* Conceptually, srv_innodb_monitor_mutex has a very high latching
+ order level in sync0sync.h, while dict_foreign_err_mutex has a very
+ low level 135. Therefore we can reserve the latter mutex here without
+ a danger of a deadlock of threads. */
+
+ mutex_enter(&dict_foreign_err_mutex);
+
if (*dict_foreign_err_buf != '\0') {
buf += sprintf(buf,
"------------------------\n"
@@ -1476,18 +1487,7 @@ srv_sprintf_innodb_monitor(
}
}
- 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);
- }
- }
+ mutex_exit(&dict_foreign_err_mutex);
ut_a(buf < buf_end + 1500);
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 6335b857b09..7b50877709b 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -40,7 +40,6 @@ Created 2/16/1996 Heikki Tuuri
#include "rem0rec.h"
#include "srv0srv.h"
#include "que0que.h"
-#include "com0com.h"
#include "usr0sess.h"
#include "lock0lock.h"
#include "trx0roll.h"
@@ -1300,8 +1299,6 @@ NetWare. */
mutex_exit(&(log_sys->mutex));
}
- sess_sys_init_at_db_start();
-
if (create_new_db) {
mtr_start(&mtr);
diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
index 9bcee34a7d1..8082f598b0c 100644
--- a/innobase/sync/sync0arr.c
+++ b/innobase/sync/sync0arr.c
@@ -14,6 +14,7 @@ Created 9/5/1995 Heikki Tuuri
#include "sync0sync.h"
#include "sync0rw.h"
#include "os0sync.h"
+#include "os0file.h"
#include "srv0srv.h"
/*
@@ -99,6 +100,7 @@ struct sync_array_struct {
since creation of the array */
};
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
This function is called only in the debug version. Detects a deadlock
of one or more threads because of waits of semaphores. */
@@ -112,6 +114,7 @@ sync_array_detect_deadlock(
sync_cell_t* start, /* in: cell where recursive search started */
sync_cell_t* cell, /* in: cell to search */
ulint depth); /* in: recursion depth */
+#endif /* UNIV_SYNC_DEBUG */
/*********************************************************************
Gets the nth cell in array. */
@@ -464,13 +467,17 @@ sync_array_cell_print(
mutex = cell->old_wait_mutex;
buf += sprintf(buf,
- "Mutex at %lx created file %s line %lu, lock var %lu\n",
- (ulong) mutex, mutex->cfile_name,
- (ulong) mutex->cline, (ulong) mutex->lock_word);
- buf += sprintf(buf,
- "Last time reserved in file %s line %lu, waiters flag %lu\n",
- mutex->file_name, (ulong) mutex->line,
- (ulong) mutex->waiters);
+ "Mutex at %p created file %s line %lu, lock var %lu\n"
+#ifdef UNIV_SYNC_DEBUG
+ "Last time reserved in file %s line %lu, "
+#endif /* UNIV_SYNC_DEBUG */
+ "waiters flag %lu\n",
+ mutex, mutex->cfile_name, (ulong) mutex->cline,
+ (ulong) mutex->lock_word,
+#ifdef UNIV_SYNC_DEBUG
+ mutex->file_name, (ulong) mutex->line,
+#endif /* UNIV_SYNC_DEBUG */
+ (ulong) mutex->waiters);
} else if (type == RW_LOCK_EX || type == RW_LOCK_SHARED) {
@@ -522,6 +529,7 @@ sync_array_cell_print(
}
}
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Looks for a cell with the given thread id. */
static
@@ -693,7 +701,6 @@ sync_array_detect_deadlock(
sync_array_cell_print(buf, cell);
printf("rw-lock %lx %s ", (ulong) lock, buf);
rw_lock_debug_print(debug);
-
return(TRUE);
}
}
@@ -743,6 +750,7 @@ sync_array_detect_deadlock(
return(TRUE); /* Execution never reaches this line: for compiler
fooling only */
}
+#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Determines if we can wake up the thread waiting for a sempahore. */
@@ -936,7 +944,7 @@ sync_array_print_long_waits(void)
"InnoDB: We intentionally crash the server, because it appears to be hung.\n"
);
- ut_a(0);
+ ut_error;
}
}
@@ -945,6 +953,16 @@ sync_array_print_long_waits(void)
"InnoDB: ###### Starts InnoDB Monitor for 30 secs to print diagnostic info:\n");
old_val = srv_print_innodb_monitor;
+ /* If some crucial semaphore is reserved, then also the InnoDB
+ Monitor can hang, and we do not get diagnostics. Since in
+ many cases an InnoDB hang is caused by a pwrite() or a pread()
+ call hanging inside the operating system, let us print right
+ now the values of pending calls of these. */
+
+ fprintf(stderr,
+"InnoDB: Pending preads %lu, pwrites %lu\n", (ulong)os_file_n_pending_preads,
+ (ulong)os_file_n_pending_pwrites);
+
srv_print_innodb_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
index e6da03c53fa..93fd9f14575 100644
--- a/innobase/sync/sync0rw.c
+++ b/innobase/sync/sync0rw.c
@@ -31,6 +31,7 @@ ulint rw_x_exit_count = 0;
rw_lock_list_t rw_lock_list;
mutex_t rw_lock_list_mutex;
+#ifdef UNIV_SYNC_DEBUG
/* The global mutex which protects debug info lists of all rw-locks.
To modify the debug info list of an rw-lock, this mutex has to be
acquired in addition to the mutex protecting the lock. */
@@ -76,6 +77,7 @@ rw_lock_debug_free(
{
mem_free(info);
}
+#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Creates, or rather, initializes an rw-lock object in a specified memory
@@ -107,10 +109,12 @@ rw_lock_create_func(
lock->writer_is_wait_ex = FALSE;
+#ifdef UNIV_SYNC_DEBUG
UT_LIST_INIT(lock->debug_list);
- lock->magic_n = RW_LOCK_MAGIC_N;
lock->level = SYNC_LEVEL_NONE;
+#endif /* UNIV_SYNC_DEBUG */
+ lock->magic_n = RW_LOCK_MAGIC_N;
lock->cfile_name = cfile_name;
lock->cline = cline;
@@ -319,8 +323,9 @@ rw_lock_x_lock_low(
char* file_name,/* in: file name where lock requested */
ulint line) /* in: line where requested */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
-
+#endif /* UNIV_SYNC_DEBUG */
if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
if (rw_lock_get_reader_count(lock) == 0) {
@@ -528,6 +533,7 @@ lock_loop:
goto lock_loop;
}
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Acquires the debug mutex. We cannot use the mutex defined in sync0sync,
because the debug mutex is also acquired in sync0arr while holding the OS
@@ -653,6 +659,7 @@ rw_lock_remove_debug_info(
ut_error;
}
+#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Sets the rw-lock latching level field. */
@@ -666,6 +673,7 @@ rw_lock_set_level(
lock->level = level;
}
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Checks if the thread has locked the rw-lock in the specified mode, with
the pass value == 0. */
@@ -683,9 +691,6 @@ rw_lock_own(
ut_ad(lock);
ut_ad(rw_lock_validate(lock));
-#ifndef UNIV_SYNC_DEBUG
- ut_error;
-#endif
mutex_enter(&(lock->mutex));
info = UT_LIST_GET_FIRST(lock->debug_list);
@@ -708,6 +713,7 @@ rw_lock_own(
return(FALSE);
}
+#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Checks if somebody has locked the rw-lock in the specified mode. */
@@ -744,6 +750,7 @@ rw_lock_is_locked(
return(ret);
}
+#ifdef UNIV_SYNC_DEBUG
/*******************************************************************
Prints debug info of currently locked rw-locks. */
@@ -751,8 +758,6 @@ void
rw_lock_list_print_info(void)
/*=========================*/
{
-#ifndef UNIV_SYNC_DEBUG
-#else
rw_lock_t* lock;
ulint count = 0;
rw_lock_debug_t* info;
@@ -796,7 +801,6 @@ rw_lock_list_print_info(void)
printf("Total number of rw-locks %ld\n", count);
mutex_exit(&rw_lock_list_mutex);
-#endif
}
/*******************************************************************
@@ -807,11 +811,6 @@ rw_lock_print(
/*==========*/
rw_lock_t* lock __attribute__((unused))) /* in: rw-lock */
{
-#ifndef UNIV_SYNC_DEBUG
- printf(
- "Sorry, cannot give rw-lock info in non-debug version!\n");
-#else
- ulint count = 0;
rw_lock_debug_t* info;
printf("-------------\n");
@@ -834,7 +833,6 @@ rw_lock_print(
info = UT_LIST_GET_NEXT(list, info);
}
}
-#endif
}
/*************************************************************************
@@ -875,12 +873,6 @@ ulint
rw_lock_n_locked(void)
/*==================*/
{
-#ifndef UNIV_SYNC_DEBUG
- printf(
- "Sorry, cannot give rw-lock info in non-debug version!\n");
- ut_error;
- return(0);
-#else
rw_lock_t* lock;
ulint count = 0;
@@ -903,5 +895,5 @@ rw_lock_n_locked(void)
mutex_exit(&rw_lock_list_mutex);
return(count);
-#endif
}
+#endif /* UNIV_SYNC_DEBUG */
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 22e0975dd37..6ad766d8bc8 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -188,8 +188,10 @@ mutex_create_func(
#endif
mutex_set_waiters(mutex, 0);
mutex->magic_n = MUTEX_MAGIC_N;
+#ifdef UNIV_SYNC_DEBUG
mutex->line = 0;
mutex->file_name = (char *) "not yet reserved";
+#endif /* UNIV_SYNC_DEBUG */
mutex->level = SYNC_LEVEL_NONE;
mutex->cfile_name = cfile_name;
mutex->cline = cline;
@@ -266,9 +268,11 @@ mutex_enter_nowait(
/*===============*/
/* out: 0 if succeed, 1 if not */
mutex_t* mutex, /* in: pointer to mutex */
- char* file_name, /* in: file name where mutex
+ char* file_name __attribute__((unused)),
+ /* in: file name where mutex
requested */
- ulint line) /* in: line where requested */
+ ulint line __attribute__((unused)))
+ /* in: line where requested */
{
ut_ad(mutex_validate(mutex));
@@ -277,9 +281,6 @@ mutex_enter_nowait(
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
-
- mutex->file_name = file_name;
- mutex->line = line;
return(0); /* Succeeded! */
}
@@ -379,9 +380,6 @@ spin_loop:
mutex_set_debug_info(mutex, file_name, line);
#endif
- mutex->file_name = file_name;
- mutex->line = line;
-
return;
}
@@ -426,9 +424,6 @@ spin_loop:
mutex_set_debug_info(mutex, file_name, line);
#endif
- mutex->file_name = file_name;
- mutex->line = line;
-
if (srv_print_latch_waits) {
printf(
"Thread %lu spin wait succeeds at 2: mutex at %lx\n",
@@ -479,6 +474,7 @@ mutex_signal_object(
sync_array_signal_object(sync_primary_wait_array, mutex);
}
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Sets the debug information for a reserved mutex. */
@@ -516,7 +512,8 @@ mutex_get_debug_info(
*file_name = mutex->file_name;
*line = mutex->line;
*thread_id = mutex->thread_id;
-}
+}
+#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Sets the mutex latching level field. */
@@ -530,6 +527,7 @@ mutex_set_level(
mutex->level = level;
}
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Checks that the current thread owns the mutex. Works only in the debug
version. */
@@ -562,8 +560,6 @@ void
mutex_list_print_info(void)
/*=======================*/
{
-#ifndef UNIV_SYNC_DEBUG
-#else
mutex_t* mutex;
char* file_name;
ulint line;
@@ -596,7 +592,6 @@ mutex_list_print_info(void)
printf("Total number of mutexes %ld\n", count);
mutex_exit(&mutex_list_mutex);
-#endif
}
/**********************************************************************
@@ -606,12 +601,6 @@ ulint
mutex_n_reserved(void)
/*==================*/
{
-#ifndef UNIV_SYNC_DEBUG
- printf("Sorry, cannot give mutex info in non-debug version!\n");
- ut_error;
-
- return(0);
-#else
mutex_t* mutex;
ulint count = 0;
@@ -634,7 +623,6 @@ mutex_n_reserved(void)
return(count - 1); /* Subtract one, because this function itself
was holding one mutex (mutex_list_mutex) */
-#endif
}
/**********************************************************************
@@ -645,19 +633,9 @@ ibool
sync_all_freed(void)
/*================*/
{
-#ifdef UNIV_SYNC_DEBUG
- if (mutex_n_reserved() + rw_lock_n_locked() == 0) {
-
- return(TRUE);
- } else {
- return(FALSE);
- }
-#else
- ut_error;
-
- return(FALSE);
-#endif
+ return(mutex_n_reserved() + rw_lock_n_locked() == 0);
}
+#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Gets the value in the nth slot in the thread level arrays. */
@@ -754,9 +732,6 @@ sync_thread_levels_g(
thread */
ulint limit) /* in: level limit */
{
- char* file_name;
- ulint line;
- os_thread_id_t thread_id;
sync_level_t* slot;
rw_lock_t* lock;
mutex_t* mutex;
@@ -781,18 +756,28 @@ sync_thread_levels_g(
(ulong) mutex->cline);
if (mutex_get_lock_word(mutex) != 0) {
+#ifdef UNIV_SYNC_DEBUG
+ char* file_name;
+ ulint line;
+ os_thread_id_t thread_id;
mutex_get_debug_info(mutex,
&file_name, &line, &thread_id);
- printf("InnoDB: Locked mutex: addr %lx thread %ld file %s line %ld\n",
- (ulong) mutex, (ulong) os_thread_pf(thread_id),
- file_name, (ulong) line);
+ fprintf(stderr,
+ "InnoDB: Locked mutex: addr %p thread %ld file %s line %ld\n",
+ mutex, os_thread_pf(thread_id), file_name, (ulong) line);
+#else /* UNIV_SYNC_DEBUG */
+ fprintf(stderr,
+ "InnoDB: Locked mutex: addr %p\n", mutex);
+#endif /* UNIV_SYNC_DEBUG */
} else {
- printf("Not locked\n");
+ fputs("Not locked\n", stderr);
}
} else {
+#ifdef UNIV_SYNC_DEBUG
rw_lock_print(lock);
+#endif /* UNIV_SYNC_DEBUG */
}
return(FALSE);
@@ -932,7 +917,9 @@ sync_thread_add_level(
if ((latch == (void*)&sync_thread_mutex)
|| (latch == (void*)&mutex_list_mutex)
+#ifdef UNIV_SYNC_DEBUG
|| (latch == (void*)&rw_lock_debug_mutex)
+#endif /* UNIV_SYNC_DEBUG */
|| (latch == (void*)&rw_lock_list_mutex)) {
return;
@@ -1112,7 +1099,9 @@ sync_thread_reset_level(
if ((latch == (void*)&sync_thread_mutex)
|| (latch == (void*)&mutex_list_mutex)
+#ifdef UNIV_SYNC_DEBUG
|| (latch == (void*)&rw_lock_debug_mutex)
+#endif /* UNIV_SYNC_DEBUG */
|| (latch == (void*)&rw_lock_list_mutex)) {
return(FALSE);
@@ -1198,11 +1187,13 @@ sync_init(void)
mutex_create(&rw_lock_list_mutex);
mutex_set_level(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
+#ifdef UNIV_SYNC_DEBUG
mutex_create(&rw_lock_debug_mutex);
mutex_set_level(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
rw_lock_debug_event = os_event_create(NULL);
rw_lock_debug_waiters = FALSE;
+#endif /* UNIV_SYNC_DEBUG */
}
/**********************************************************************
@@ -1267,9 +1258,11 @@ sync_print(
char* buf, /* in/out: buffer where to print */
char* buf_end) /* in: buffer end */
{
+#ifdef UNIV_SYNC_DEBUG
mutex_list_print_info();
rw_lock_list_print_info();
+#endif /* UNIV_SYNC_DEBUG */
sync_array_print_info(buf, buf_end, sync_primary_wait_array);
diff --git a/innobase/thr/thr0loc.c b/innobase/thr/thr0loc.c
index 839cb024f25..a17d09fcca6 100644
--- a/innobase/thr/thr0loc.c
+++ b/innobase/thr/thr0loc.c
@@ -46,10 +46,11 @@ struct thr_local_struct{
ibool in_ibuf;/* TRUE if the the thread is doing an ibuf
operation */
hash_node_t hash; /* hash chain node */
+#ifdef UNIV_DEBUG
ulint magic_n;
-};
-
#define THR_LOCAL_MAGIC_N 1231234
+#endif /* UNIV_DEBUG */
+};
/***********************************************************************
Returns the local storage struct for a thread. */
@@ -64,7 +65,9 @@ thr_local_get(
try_again:
ut_ad(thr_local_hash);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&thr_local_mutex));
+#endif /* UNIV_SYNC_DEBUG */
/* Look for the local struct in the hash table */
@@ -167,8 +170,9 @@ thr_local_create(void)
local->id = os_thread_get_curr_id();
local->handle = os_thread_get_curr();
+#ifdef UNIV_DEBUG
local->magic_n = THR_LOCAL_MAGIC_N;
-
+#endif /* UNIV_DEBUG */
local->in_ibuf = FALSE;
mutex_enter(&thr_local_mutex);
@@ -207,7 +211,7 @@ thr_local_free(
mutex_exit(&thr_local_mutex);
- ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
mem_free(local);
}
diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c
index 31223aa280e..558a0825fd7 100644
--- a/innobase/trx/trx0purge.c
+++ b/innobase/trx/trx0purge.c
@@ -45,7 +45,9 @@ trx_purge_update_undo_must_exist(
the undo log still exists in the system */
dulint trx_id) /* in: transaction id */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
if (!read_view_sees_trx_id(purge_sys->view, trx_id)) {
@@ -195,9 +197,9 @@ void
trx_purge_sys_create(void)
/*======================*/
{
- com_endpoint_t* com_endpoint;
-
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
purge_sys = mem_alloc(sizeof(trx_purge_t));
@@ -219,9 +221,7 @@ trx_purge_sys_create(void)
purge_sys->arr = trx_undo_arr_create();
- com_endpoint = (com_endpoint_t*)purge_sys; /* This is a dummy non-NULL
- value */
- purge_sys->sess = sess_open(com_endpoint, (byte*)"purge_system", 13);
+ purge_sys->sess = sess_open();
purge_sys->trx = purge_sys->sess->trx;
@@ -262,7 +262,9 @@ trx_purge_add_update_undo_to_history(
ut_ad(undo);
rseg = undo->rseg;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(rseg->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, mtr);
@@ -276,7 +278,7 @@ trx_purge_add_update_undo_to_history(
if (undo->id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n", (ulong) undo->id);
- ut_a(0);
+ ut_error;
}
trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL, mtr);
@@ -295,8 +297,7 @@ trx_purge_add_update_undo_to_history(
undo_header + TRX_UNDO_HISTORY_NODE, mtr);
/* Write the trx number to the undo log header */
- mlog_write_dulint(undo_header + TRX_UNDO_TRX_NO, trx->no, MLOG_8BYTES,
- mtr);
+ mlog_write_dulint(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr);
/* Write information about delete markings to the undo log header */
if (!undo->del_marks) {
@@ -338,7 +339,9 @@ trx_purge_free_segment(
/* printf("Freeing an update undo log segment\n"); */
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(purge_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
loop:
mtr_start(&mtr);
mutex_enter(&(rseg->mutex));
@@ -434,7 +437,9 @@ trx_purge_truncate_rseg_history(
ulint n_removed_logs = 0;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(purge_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
mtr_start(&mtr);
mutex_enter(&(rseg->mutex));
@@ -520,7 +525,9 @@ trx_purge_truncate_history(void)
dulint limit_trx_no;
dulint limit_undo_no;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(purge_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
trx_purge_arr_get_biggest(purge_sys->arr, &limit_trx_no,
&limit_undo_no);
@@ -560,7 +567,9 @@ trx_purge_truncate_if_arr_empty(void)
/*=================================*/
/* out: TRUE if array empty */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(purge_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (purge_sys->arr->n_used == 0) {
@@ -589,7 +598,9 @@ trx_purge_rseg_get_next_history_log(
ibool del_marks;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(purge_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(rseg->mutex));
@@ -669,7 +680,9 @@ trx_purge_choose_next_log(void)
ulint offset = 0; /* remove warning (??? bug ???) */
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(purge_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(purge_sys->next_stored == FALSE);
rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
@@ -770,7 +783,9 @@ trx_purge_get_next_rec(
ulint cmpl_info;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(purge_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(purge_sys->next_stored);
space = purge_sys->rseg->space;
@@ -1001,7 +1016,7 @@ trx_purge(void)
/* Should not happen */
- ut_a(0);
+ ut_error;
return(0);
}
@@ -1034,11 +1049,11 @@ trx_purge(void)
mutex_enter(&kernel_mutex);
- thr = que_fork_start_command(purge_sys->query, SESS_COMM_EXECUTE, 0);
+ thr = que_fork_start_command(purge_sys->query);
ut_ad(thr);
-/* thr2 = que_fork_start_command(purge_sys->query, SESS_COMM_EXECUTE, 0);
+/* thr2 = que_fork_start_command(purge_sys->query);
ut_ad(thr2); */
diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c
index e10f019ac13..bd37a4b506b 100644
--- a/innobase/trx/trx0rec.c
+++ b/innobase/trx/trx0rec.c
@@ -1070,7 +1070,9 @@ trx_undo_report_row_operation(
IB__FILE__, __LINE__,
&mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(undo_page, SYNC_TRX_UNDO_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
if (op_type == TRX_UNDO_INSERT_OP) {
offset = trx_undo_page_report_insert(undo_page, trx,
@@ -1197,7 +1199,9 @@ trx_undo_get_undo_rec(
trx_undo_rec_t** undo_rec, /* out, own: copy of the record */
mem_heap_t* heap) /* in: memory heap where copied */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
if (!trx_purge_update_undo_must_exist(trx_id)) {
@@ -1257,7 +1261,9 @@ trx_undo_prev_version_build(
ulint i;
char err_buf[1000];
+#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(mtr_memo_contains(index_mtr, buf_block_align(index_rec),
MTR_MEMO_PAGE_S_FIX) ||
mtr_memo_contains(index_mtr, buf_block_align(index_rec),
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index 1f053aeed89..6a25304c7ef 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -73,8 +73,7 @@ trx_general_rollback_for_mysql(
thr = pars_complete_graph_for_exec(roll_node, trx, heap);
- ut_a(thr == que_fork_start_command(que_node_get_parent(thr),
- SESS_COMM_EXECUTE, 0));
+ ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
que_run_threads(thr);
mutex_enter(&kernel_mutex);
@@ -354,8 +353,7 @@ trx_rollback_or_clean_all_without_sess(void)
/* Open a dummy session */
if (!trx_dummy_sess) {
- trx_dummy_sess = sess_open(NULL, (byte*)"Dummy sess",
- ut_strlen((char *) "Dummy sess"));
+ trx_dummy_sess = sess_open();
}
mutex_exit(&kernel_mutex);
@@ -418,7 +416,7 @@ loop:
trx->graph = fork;
- ut_a(thr == que_fork_start_command(fork, SESS_COMM_EXECUTE, 0));
+ ut_a(thr == que_fork_start_command(fork));
trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no);
trx_roll_progress_printed_pct = 0;
@@ -678,8 +676,10 @@ trx_roll_try_truncate(
dulint limit;
dulint biggest;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(trx->undo_mutex)));
ut_ad(mutex_own(&((trx->rseg)->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
trx->pages_undone = 0;
@@ -722,7 +722,9 @@ trx_roll_pop_top_rec(
trx_undo_rec_t* prev_rec;
page_t* prev_rec_page;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(trx->undo_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
undo_page = trx_undo_page_get_s_latched(undo->space,
undo->top_page_no, mtr);
@@ -946,7 +948,9 @@ trx_rollback(
que_thr_t* thr;
/* que_thr_t* thr2; */
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad((trx->undo_no_arr == NULL) || ((trx->undo_no_arr)->n_used == 0));
/* Initialize the rollback field in the transaction */
@@ -981,11 +985,11 @@ trx_rollback(
trx->graph = roll_graph;
trx->que_state = TRX_QUE_ROLLING_BACK;
- thr = que_fork_start_command(roll_graph, SESS_COMM_EXECUTE, 0);
+ thr = que_fork_start_command(roll_graph);
ut_ad(thr);
-/* thr2 = que_fork_start_command(roll_graph, SESS_COMM_EXECUTE, 0);
+/* thr2 = que_fork_start_command(roll_graph);
ut_ad(thr2); */
@@ -1015,7 +1019,9 @@ trx_roll_graph_build(
que_thr_t* thr;
/* que_thr_t* thr2; */
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
heap = mem_heap_create(512);
fork = que_fork_create(NULL, NULL, QUE_FORK_ROLLBACK, heap);
@@ -1042,7 +1048,9 @@ trx_finish_error_processing(
trx_sig_t* sig;
trx_sig_t* next_sig;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
sig = UT_LIST_GET_FIRST(trx->signals);
@@ -1075,14 +1083,16 @@ trx_finish_partial_rollback_off_kernel(
{
trx_sig_t* sig;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
sig = UT_LIST_GET_FIRST(trx->signals);
/* Remove the signal from the signal queue and send reply message
to it */
- trx_sig_reply(trx, sig, next_thr);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
trx->que_state = TRX_QUE_RUNNING;
@@ -1106,7 +1116,9 @@ trx_finish_rollback_off_kernel(
trx_sig_t* sig;
trx_sig_t* next_sig;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(trx->undo_no_arr == NULL || trx->undo_no_arr->n_used == 0);
@@ -1145,7 +1157,7 @@ trx_finish_rollback_off_kernel(
if (sig->type == TRX_SIG_TOTAL_ROLLBACK) {
- trx_sig_reply(trx, sig, next_thr);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
}
@@ -1213,7 +1225,7 @@ trx_rollback_step(
success = trx_sig_send(thr_get_trx(thr),
sig_no, TRX_SIG_SELF,
- TRUE, thr, savept, NULL);
+ thr, savept, NULL);
thr->state = QUE_THR_SIG_REPLY_WAIT;
diff --git a/innobase/trx/trx0rseg.c b/innobase/trx/trx0rseg.c
index b1fb8a9539c..e3885c86def 100644
--- a/innobase/trx/trx0rseg.c
+++ b/innobase/trx/trx0rseg.c
@@ -60,7 +60,9 @@ trx_rseg_header_create(
page_t* page;
ut_ad(mtr);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space),
MTR_MEMO_X_LOCK));
sys_header = trx_sysf_get(mtr);
@@ -81,7 +83,9 @@ trx_rseg_header_create(
return(FIL_NULL);
}
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_RSEG_HEADER_NEW);
+#endif /* UNIV_SYNC_DEBUG */
page_no = buf_frame_get_page_no(page);
@@ -132,7 +136,9 @@ trx_rseg_mem_create(
fil_addr_t node_addr;
ulint sum_of_undo_sizes;
- ut_ad(mutex_own(&kernel_mutex));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
rseg = mem_alloc(sizeof(trx_rseg_t));
@@ -173,8 +179,7 @@ trx_rseg_mem_create(
+ node_addr.boffset;
rseg->last_trx_no = mtr_read_dulint(
- undo_log_hdr + TRX_UNDO_TRX_NO,
- MLOG_8BYTES, mtr);
+ undo_log_hdr + TRX_UNDO_TRX_NO, mtr);
rseg->last_del_marks = mtr_read_ulint(
undo_log_hdr + TRX_UNDO_DEL_MARKS,
MLOG_2BYTES, mtr);
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index 6084c70102f..57cfcef7d6f 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -134,7 +134,9 @@ trx_sys_mark_upgraded_to_multiple_tablespaces(void)
mtr_start(&mtr);
page = buf_page_get(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
doublewrite = page + TRX_SYS_DOUBLEWRITE;
@@ -177,7 +179,9 @@ start_again:
mtr_start(&mtr);
page = buf_page_get(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
doublewrite = page + TRX_SYS_DOUBLEWRITE;
@@ -211,7 +215,9 @@ start_again:
/* fseg_create acquires a second latch on the page,
therefore we must declare it: */
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page2, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
if (page2 == NULL) {
fprintf(stderr,
@@ -254,7 +260,9 @@ start_again:
new_page = buf_page_get(TRX_SYS_SPACE, page_no,
RW_X_LATCH, &mtr);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(new_page, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
/* Make a dummy change to the page to ensure it will
be written to disk in a flush */
@@ -510,7 +518,9 @@ trx_in_trx_list(
{
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
@@ -537,14 +547,16 @@ trx_sys_flush_max_trx_id(void)
trx_sysf_t* sys_header;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
mtr_start(&mtr);
sys_header = trx_sysf_get(&mtr);
mlog_write_dulint(sys_header + TRX_SYS_TRX_ID_STORE,
- trx_sys->max_trx_id, MLOG_8BYTES, &mtr);
+ trx_sys->max_trx_id, &mtr);
mtr_commit(&mtr);
}
@@ -736,7 +748,9 @@ trx_sysf_rseg_find_free(
ulint page_no;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(kernel_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
sys_header = trx_sysf_get(mtr);
@@ -782,13 +796,15 @@ trx_sysf_create(
mtr);
ut_a(buf_frame_get_page_no(page) == TRX_SYS_PAGE_NO);
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TRX_SYS_HEADER);
+#endif /* UNIV_SYNC_DEBUG */
sys_header = trx_sysf_get(mtr);
/* Start counting transaction ids from number 1 up */
mlog_write_dulint(sys_header + TRX_SYS_TRX_ID_STORE,
- ut_dulint_create(0, 1), MLOG_8BYTES, mtr);
+ ut_dulint_create(0, 1), mtr);
/* Reset the rollback segment slots */
for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
@@ -843,8 +859,7 @@ trx_sys_init_at_db_start(void)
trx_sys->max_trx_id = ut_dulint_add(
ut_dulint_align_up(
mtr_read_dulint(sys_header
- + TRX_SYS_TRX_ID_STORE,
- MLOG_8BYTES, &mtr),
+ + TRX_SYS_TRX_ID_STORE, &mtr),
TRX_SYS_TRX_ID_WRITE_MARGIN),
2 * TRX_SYS_TRX_ID_WRITE_MARGIN);
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 0197e5cc05f..54358ad3d4c 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -73,7 +73,9 @@ trx_create(
{
trx_t* trx;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
trx = mem_alloc(sizeof(trx_t));
@@ -171,8 +173,7 @@ trx_allocate_for_mysql(void)
/* Open a dummy session */
if (!trx_dummy_sess) {
- trx_dummy_sess = sess_open(NULL, (byte*)"Dummy sess",
- ut_strlen((char *) "Dummy sess"));
+ trx_dummy_sess = sess_open();
}
trx = trx_create(trx_dummy_sess);
@@ -205,8 +206,7 @@ trx_allocate_for_background(void)
/* Open a dummy session */
if (!trx_dummy_sess) {
- trx_dummy_sess = sess_open(NULL, (byte*)"Dummy sess",
- ut_strlen("Dummy sess"));
+ trx_dummy_sess = sess_open();
}
trx = trx_create(trx_dummy_sess);
@@ -241,7 +241,9 @@ trx_free(
{
char err_buf[1000];
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (trx->declared_to_be_inside_innodb) {
ut_print_timestamp(stderr);
@@ -347,7 +349,9 @@ trx_list_insert_ordered(
{
trx_t* trx2;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
trx2 = UT_LIST_GET_FIRST(trx_sys->trx_list);
@@ -509,7 +513,9 @@ trx_assign_rseg(void)
{
trx_rseg_t* rseg = trx_sys->latest_rseg;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
loop:
/* Get next rseg in a round-robin fashion */
@@ -546,7 +552,9 @@ trx_start_low(
{
trx_rseg_t* rseg;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(trx->rseg == NULL);
if (trx->type == TRX_PURGE) {
@@ -621,7 +629,9 @@ trx_commit_off_kernel(
ibool must_flush_log = FALSE;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
rseg = trx->rseg;
@@ -691,11 +701,13 @@ trx_commit_off_kernel(
TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
}
- /* If we did not take the shortcut, the following call
- commits the mini-transaction, making the whole transaction
- committed in the file-based world at this log sequence number;
- otherwise, we get the commit lsn from the call of
- trx_undo_update_cleanup_by_discard above.
+ /* The following call commits the mini-transaction, making the
+ whole transaction committed in the file-based world, at this
+ log sequence number. The transaction becomes 'durable' when
+ we write the log to disk, but in the logical sense the commit
+ in the file-based data structures (undo logs etc.) happens
+ here.
+
NOTE that transaction numbers, which are assigned only to
transactions with an update undo log, do not necessarily come
in exactly the same order as commit lsn's, if the transactions
@@ -715,7 +727,9 @@ trx_commit_off_kernel(
}
ut_ad(trx->conc_state == TRX_ACTIVE);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
/* The following assignment makes the transaction committed in memory
and makes its changes to data visible to other transactions.
@@ -804,7 +818,7 @@ trx_commit_off_kernel(
log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
} else {
- ut_a(0);
+ ut_error;
}
trx->commit_lsn = lsn;
@@ -895,7 +909,9 @@ trx_handle_commit_sig_off_kernel(
trx_sig_t* sig;
trx_sig_t* next_sig;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
trx->que_state = TRX_QUE_COMMITTING;
@@ -913,7 +929,7 @@ trx_handle_commit_sig_off_kernel(
if (sig->type == TRX_SIG_COMMIT) {
- trx_sig_reply(trx, sig, next_thr);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
}
@@ -935,7 +951,9 @@ trx_end_lock_wait(
{
que_thr_t* thr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT);
thr = UT_LIST_GET_FIRST(trx->wait_thrs);
@@ -962,7 +980,9 @@ trx_lock_wait_to_suspended(
{
que_thr_t* thr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT);
thr = UT_LIST_GET_FIRST(trx->wait_thrs);
@@ -990,7 +1010,9 @@ trx_sig_reply_wait_to_suspended(
trx_sig_t* sig;
que_thr_t* thr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
sig = UT_LIST_GET_FIRST(trx->reply_signals);
@@ -1002,7 +1024,6 @@ trx_sig_reply_wait_to_suspended(
thr->state = QUE_THR_SUSPENDED;
sig->receiver = NULL;
- sig->reply = FALSE;
UT_LIST_REMOVE(reply_signals, trx->reply_signals, sig);
@@ -1024,7 +1045,9 @@ trx_sig_is_compatible(
{
trx_sig_t* sig;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (UT_LIST_GET_LEN(trx->signals) == 0) {
@@ -1096,13 +1119,9 @@ trx_sig_send(
ulint type, /* in: signal type */
ulint sender, /* in: TRX_SIG_SELF or
TRX_SIG_OTHER_SESS */
- ibool reply, /* in: TRUE if the sender of the signal
- wants reply after the operation induced
- by the signal is completed; if type
- is TRX_SIG_END_WAIT, this must be
- FALSE */
que_thr_t* receiver_thr, /* in: query thread which wants the
- reply, or NULL */
+ reply, or NULL; if type is
+ TRX_SIG_END_WAIT, this must be NULL */
trx_savept_t* savept, /* in: possible rollback savepoint, or
NULL */
que_thr_t** next_thr) /* in/out: next query thread to run;
@@ -1116,13 +1135,15 @@ trx_sig_send(
trx_t* receiver_trx;
ut_ad(trx);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (!trx_sig_is_compatible(trx, type, sender)) {
/* The signal is not compatible with the other signals in
the queue: do nothing */
- ut_a(0);
+ ut_error;
return(FALSE);
}
@@ -1146,7 +1167,6 @@ trx_sig_send(
sig->type = type;
sig->state = TRX_SIG_WAITING;
sig->sender = sender;
- sig->reply = reply;
sig->receiver = receiver_thr;
if (savept) {
@@ -1171,7 +1191,7 @@ trx_sig_send(
signal to the end of the queue, if the session is not yet
in the error state: */
- ut_a(0);
+ ut_error;
}
/* If there were no other signals ahead in the queue, try to start
@@ -1196,7 +1216,9 @@ trx_end_signal_handling(
/*====================*/
trx_t* trx) /* in: trx */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(trx->handling_signals == TRUE);
trx->handling_signals = FALSE;
@@ -1230,7 +1252,9 @@ loop:
we can process immediately */
ut_ad(trx);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
if (trx->handling_signals && (UT_LIST_GET_LEN(trx->signals) == 0)) {
@@ -1305,7 +1329,7 @@ loop:
} else if (type == TRX_SIG_BREAK_EXECUTION) {
- trx_sig_reply(trx, sig, next_thr);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
} else {
ut_error;
@@ -1321,7 +1345,6 @@ handled. */
void
trx_sig_reply(
/*==========*/
- trx_t* trx, /* in: trx handle */
trx_sig_t* sig, /* in: signal */
que_thr_t** next_thr) /* in/out: next query thread to run;
if the value which is passed in is
@@ -1331,11 +1354,12 @@ trx_sig_reply(
{
trx_t* receiver_trx;
- ut_ad(trx && sig);
+ ut_ad(sig);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
- if (sig->reply && (sig->receiver != NULL)) {
-
+ if (sig->receiver != NULL) {
ut_ad((sig->receiver)->state == QUE_THR_SIG_REPLY_WAIT);
receiver_trx = thr_get_trx(sig->receiver);
@@ -1346,18 +1370,8 @@ trx_sig_reply(
que_thr_end_wait(sig->receiver, next_thr);
- sig->reply = FALSE;
- sig->receiver = NULL;
-
- } else if (sig->reply) {
- /* In this case the reply should be sent to the client of
- the session of the transaction */
-
- sig->reply = FALSE;
sig->receiver = NULL;
- sess_srv_msg_send_simple(trx->sess, SESS_SRV_SUCCESS,
- SESS_NOT_RELEASE_KERNEL);
}
}
@@ -1371,9 +1385,10 @@ trx_sig_remove(
trx_sig_t* sig) /* in, own: signal */
{
ut_ad(trx && sig);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
- ut_ad(sig->reply == FALSE);
ut_ad(sig->receiver == NULL);
UT_LIST_REMOVE(signals, trx->signals, sig);
@@ -1435,8 +1450,7 @@ trx_commit_step(
/* Send the commit signal to the transaction */
success = trx_sig_send(thr_get_trx(thr), TRX_SIG_COMMIT,
- TRX_SIG_SELF, TRUE, thr, NULL,
- &next_thr);
+ TRX_SIG_SELF, thr, NULL, &next_thr);
mutex_exit(&kernel_mutex);
@@ -1522,7 +1536,7 @@ trx_commit_complete_for_mysql(
log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
} else {
- ut_a(0);
+ ut_error;
}
trx->op_info = (char*)"";
diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c
index f3f93734a49..0a47134c163 100644
--- a/innobase/trx/trx0undo.c
+++ b/innobase/trx/trx0undo.c
@@ -391,7 +391,9 @@ trx_undo_seg_create(
ibool success;
ut_ad(mtr && id && rseg_hdr);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(rseg->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
/*
if (type == TRX_UNDO_INSERT) {
printf("Creating insert undo log segment\n");
@@ -431,7 +433,9 @@ trx_undo_seg_create(
return(NULL);
}
+#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(undo_page, SYNC_TRX_UNDO_PAGE);
+#endif /* UNIV_SYNC_DEBUG */
page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
@@ -737,13 +741,14 @@ trx_undo_add_page(
ulint n_reserved;
ibool success;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(trx->undo_mutex)));
ut_ad(!mutex_own(&kernel_mutex));
+ ut_ad(mutex_own(&(trx->rseg->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
rseg = trx->rseg;
- ut_ad(mutex_own(&(rseg->mutex)));
-
if (rseg->curr_size == rseg->max_size) {
return(FIL_NULL);
@@ -813,8 +818,10 @@ trx_undo_free_page(
UT_NOT_USED(hdr_offset);
ut_a(hdr_page_no != page_no);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
ut_ad(mutex_own(&(rseg->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
undo_page = trx_undo_page_get(space, page_no, mtr);
@@ -861,7 +868,9 @@ trx_undo_free_page_in_rollback(
ulint last_page_no;
ut_ad(undo->hdr_page_no != page_no);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(trx->undo_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
undo->hdr_page_no, undo->hdr_offset,
@@ -915,12 +924,13 @@ trx_undo_truncate_end(
trx_rseg_t* rseg;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(trx->undo_mutex)));
+ ut_ad(mutex_own(&(trx->rseg->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
rseg = trx->rseg;
- ut_ad(mutex_own(&(rseg->mutex)));
-
for (;;) {
mtr_start(&mtr);
@@ -994,7 +1004,9 @@ trx_undo_truncate_start(
ulint page_no;
mtr_t mtr;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(rseg->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (0 == ut_dulint_cmp(limit, ut_dulint_zero)) {
@@ -1060,8 +1072,9 @@ trx_undo_seg_free(
while (!finished) {
mtr_start(&mtr);
-
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(rseg->mutex));
seg_header = trx_undo_page_get(undo->space, undo->hdr_page_no,
@@ -1117,7 +1130,7 @@ trx_undo_mem_create_at_db_start(
if (id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n", (ulong) id);
- ut_a(0);
+ ut_error;
}
undo_page = trx_undo_page_get(rseg->space, page_no, mtr);
@@ -1134,8 +1147,7 @@ trx_undo_mem_create_at_db_start(
undo_header = undo_page + offset;
- trx_id = mtr_read_dulint(undo_header + TRX_UNDO_TRX_ID, MLOG_8BYTES,
- mtr);
+ trx_id = mtr_read_dulint(undo_header + TRX_UNDO_TRX_ID, mtr);
mutex_enter(&(rseg->mutex));
undo = trx_undo_mem_create(rseg, id, type, trx_id, page_no, offset);
@@ -1145,8 +1157,7 @@ trx_undo_mem_create_at_db_start(
undo->dict_operation = mtr_read_ulint(
undo_header + TRX_UNDO_DICT_OPERATION,
MLOG_2BYTES, mtr);
- undo->table_id = mtr_read_dulint(undo_header + TRX_UNDO_TABLE_ID,
- MLOG_8BYTES, mtr);
+ undo->table_id = mtr_read_dulint(undo_header + TRX_UNDO_TABLE_ID, mtr);
undo->state = state;
undo->size = flst_get_len(seg_header + TRX_UNDO_PAGE_LIST, mtr);
@@ -1270,12 +1281,14 @@ trx_undo_mem_create(
{
trx_undo_t* undo;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(rseg->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n", (ulong) id);
- ut_a(0);
+ ut_error;
}
undo = mem_alloc(sizeof(trx_undo_t));
@@ -1314,14 +1327,16 @@ trx_undo_mem_init_for_reuse(
is created */
ulint offset) /* in: undo log header byte offset on page */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&((undo->rseg)->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (undo->id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
(ulong) undo->id);
mem_analyze_corruption((byte*)undo);
- ut_a(0);
+ ut_error;
}
undo->state = TRX_UNDO_ACTIVE;
@@ -1345,7 +1360,7 @@ trx_undo_mem_free(
if (undo->id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n", (ulong) undo->id);
- ut_a(0);
+ ut_error;
}
mem_free(undo);
@@ -1373,7 +1388,9 @@ trx_undo_create(
trx_undo_t* undo;
page_t* undo_page;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(rseg->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (rseg->curr_size == rseg->max_size) {
@@ -1424,7 +1441,9 @@ trx_undo_reuse_cached(
page_t* undo_page;
ulint offset;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(rseg->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
if (type == TRX_UNDO_INSERT) {
@@ -1448,13 +1467,12 @@ trx_undo_reuse_cached(
}
ut_ad(undo->size == 1);
- ut_ad(undo->hdr_page_no == undo->top_page_no);
if (undo->id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
(ulong) undo->id);
mem_analyze_corruption((byte*)undo);
- ut_a(0);
+ ut_error;
}
undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
@@ -1495,7 +1513,7 @@ trx_undo_mark_as_dict_operation(
trx->dict_operation, MLOG_2BYTES, mtr);
mlog_write_dulint(hdr_page + undo->hdr_offset + TRX_UNDO_TABLE_ID,
- trx->table_id, MLOG_8BYTES, mtr);
+ trx->table_id, mtr);
undo->dict_operation = trx->dict_operation;
undo->table_id = trx->table_id;
@@ -1522,11 +1540,15 @@ trx_undo_assign_undo(
rseg = trx->rseg;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(trx->undo_mutex)));
+#endif /* UNIV_SYNC_DEBUG */
mtr_start(&mtr);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(rseg->mutex));
undo = trx_undo_reuse_cached(rseg, type, trx->id, &mtr);
@@ -1587,7 +1609,7 @@ trx_undo_set_state_at_finish(
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
(ulong) undo->id);
mem_analyze_corruption((byte*)undo);
- ut_a(0);
+ ut_error;
}
undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
@@ -1632,8 +1654,9 @@ trx_undo_update_cleanup(
undo = trx->update_undo;
rseg = trx->rseg;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(rseg->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
trx_purge_add_update_undo_to_history(trx, undo_page, mtr);
UT_LIST_REMOVE(undo_list, rseg->update_undo_list, undo);
@@ -1650,54 +1673,6 @@ trx_undo_update_cleanup(
}
}
-/**************************************************************************
-Discards an undo log and puts the segment to the list of cached update undo
-log segments. This optimized function is called if there is no need to keep
-the update undo log because there exist no read views and the transaction
-made no delete markings, which would make purge necessary. We restrict this
-to undo logs of size 1 to make things simpler. */
-
-dulint
-trx_undo_update_cleanup_by_discard(
-/*===============================*/
- /* out: log sequence number at which mtr is
- committed */
- trx_t* trx, /* in: trx owning the update undo log */
- mtr_t* mtr) /* in: mtr */
-{
- trx_rseg_t* rseg;
- trx_undo_t* undo;
- page_t* undo_page;
-
- undo = trx->update_undo;
- rseg = trx->rseg;
-
- ut_ad(mutex_own(&(rseg->mutex)));
- ut_ad(mutex_own(&kernel_mutex));
- ut_ad(undo->size == 1);
- ut_ad(undo->del_marks == FALSE);
- ut_ad(UT_LIST_GET_LEN(trx_sys->view_list) == 1);
-
- /* NOTE: we must hold the kernel mutex, because we must prevent
- creation of new read views before mtr gets committed! */
-
- undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
-
- trx_undo_discard_latest_update_undo(undo_page, mtr);
-
- undo->state = TRX_UNDO_CACHED;
-
- UT_LIST_REMOVE(undo_list, rseg->update_undo_list, undo);
-
- trx->update_undo = NULL;
-
- UT_LIST_ADD_FIRST(undo_list, rseg->update_undo_cached, undo);
-
- mtr_commit(mtr);
-
- return(mtr->end_lsn);
-}
-
/**********************************************************************
Frees or caches an insert undo log after a transaction commit or rollback.
Knowledge of inserts is not needed after a commit or rollback, therefore
diff --git a/innobase/usr/usr0sess.c b/innobase/usr/usr0sess.c
index 1455a16057e..359c1552421 100644
--- a/innobase/usr/usr0sess.c
+++ b/innobase/usr/usr0sess.c
@@ -12,21 +12,7 @@ Created 6/25/1996 Heikki Tuuri
#include "usr0sess.ic"
#endif
-#include "ut0rnd.h"
-#include "mach0data.h"
-#include "ha0ha.h"
#include "trx0trx.h"
-#include "que0que.h"
-#include "pars0pars.h"
-#include "pars0sym.h"
-#include "dict0dict.h"
-#include "dict0mem.h"
-#include "odbc0odbc.h"
-
-#define SESS_ERR_BUF_SIZE 8192
-
-/* The session system global data structure */
-sess_sys_t* sess_sys = NULL;
/*************************************************************************
Closes a session, freeing the memory occupied by it. */
@@ -35,247 +21,28 @@ void
sess_close(
/*=======*/
sess_t* sess); /* in, own: session object */
-/*************************************************************************
-Communicates an error message to the client. If sess->client_waits is not
-TRUE, puts the session to error state and does not try to send the error
-message. */
-static
-void
-sess_srv_msg_send_error(
-/*====================*/
- sess_t* sess); /* in: session object */
-/*************************************************************************
-Copies error info to a session. Sends to the transaction a signal which will
-rollback the latest incomplete SQL statement and then send the error message
-to the client. NOTE: This function will take care of the freeing of the error
-string, thus the caller must supply a copy of the error string. */
-static
-void
-sess_error_low(
-/*===========*/
- sess_t* sess, /* in: session object */
- ulint err_no, /* in: error number */
- char* err_str);/* in, own: error string or NULL;
- NOTE: the function will take care of freeing of the
- string! */
-
-/*************************************************************************
-Folds a session id to a ulint. Because this function is used also in
-calculating a checksum for the id to write in the message, it is performs
-also a XOR operation to mix the values more thoroughly. */
-UNIV_INLINE
-ulint
-sess_id_fold(
-/*=========*/
- /* out: folded value; can be used also as the checksum
- for id */
- dulint id) /* in: session id */
-{
- return(ut_fold_dulint(id) ^ 2945794411U);
-}
-
-/*************************************************************************
-Sets the session id in a client message. */
-
-void
-sess_cli_msg_set_sess(
-/*==================*/
- byte* str, /* in/out: message string */
- dulint sess_id)/* in: session id */
-{
- ulint fold;
-
- mach_write_to_8(str + SESS_CLI_MSG_SESS_ID, sess_id);
-
- fold = sess_id_fold(sess_id);
-
- mach_write_to_4(str + SESS_CLI_MSG_SESS_ID_CHECK, fold);
-}
-
-/***************************************************************************
-Decrements the reference count of a session and closes it, if desired. */
-UNIV_INLINE
-void
-sess_refer_count_dec(
-/*=================*/
- sess_t* sess) /* in: session */
-{
- ut_ad(mutex_own(&kernel_mutex));
- ut_ad(sess->refer_count > 0);
-
- sess->refer_count--;
-
- if (sess->disconnecting && (sess->refer_count == 0)) {
-
- sess_close(sess);
- }
-}
-
-/***************************************************************************
-Increments the reference count of a session. */
-UNIV_INLINE
-void
-sess_refer_count_inc(
-/*=================*/
- sess_t* sess) /* in: session */
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- sess->refer_count++;
-}
-
-/***************************************************************************
-Creates a session system at a database start. */
-
-void
-sess_sys_init_at_db_start(void)
-/*===========================*/
-{
- sess_sys = mem_alloc(sizeof(sess_sys_t));
-
- sess_sys->state = SESS_SYS_RUNNING;
- sess_sys->free_sess_id = ut_dulint_create(0, 1);
- sess_sys->hash = hash_create(SESS_HASH_SIZE);
-}
-
-/***************************************************************************
-Gets the message type of a message from client. */
-UNIV_INLINE
-ulint
-sess_cli_msg_get_type(
-/*==================*/
- /* out: message type */
- byte* str) /* in: message string */
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- return(mach_read_from_4(str + SESS_CLI_MSG_TYPE));
-}
-
-/***************************************************************************
-Gets the message number of a message from client. */
-UNIV_INLINE
-dulint
-sess_cli_msg_get_msg_no(
-/*====================*/
- /* out: message number */
- byte* str) /* in: message string */
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- return(mach_read_from_8(str + SESS_CLI_MSG_NO));
-}
-
-/***************************************************************************
-Gets the continue field of a message from client. */
-UNIV_INLINE
-ulint
-sess_cli_msg_get_continue(
-/*======================*/
- /* out: SESS_MSG_SINGLE_PART, ... */
- byte* str) /* in: message string */
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- return(mach_read_from_4(str + SESS_CLI_MSG_CONTINUE));
-}
-
-/***************************************************************************
-Gets the size of a big message in kilobytes. */
-UNIV_INLINE
-ulint
-sess_cli_msg_get_cont_size(
-/*=======================*/
- /* out: size in kilobytes */
- byte* str) /* in: message string */
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- return(mach_read_from_4(str + SESS_CLI_MSG_CONT_SIZE));
-}
-
-/*************************************************************************
-Checks the consistency of a message from a client. */
-UNIV_INLINE
-ibool
-sess_cli_msg_check_consistency(
-/*===========================*/
- /* out: TRUE if ok */
- byte* str, /* in: message string */
- ulint len) /* in: message string length */
-{
- ulint fold;
-
- ut_ad(mutex_own(&kernel_mutex));
-
- if (len < SESS_CLI_MSG_DATA) {
-
- return(FALSE);
- }
-
- ut_ad(SESS_CLI_MSG_CHECKSUM == 0);
-
- fold = ut_fold_binary(str + 4, len - 4);
-
- if (mach_read_from_4(str + SESS_CLI_MSG_CHECKSUM) != fold) {
-
- return(FALSE);
- }
-
- return(TRUE);
-}
/*************************************************************************
Opens a session. */
sess_t*
-sess_open(
-/*======*/
+sess_open(void)
+/*===========*/
/* out, own: session object */
- com_endpoint_t* endpoint, /* in: communication endpoint used
- for receiving messages from the client,
- or NULL if no client */
- byte* addr_buf, /* in: client address (= user name) */
- ulint addr_len) /* in: client address length */
{
sess_t* sess;
- ulint fold;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
-
+#endif /* UNIV_SYNC_DEBUG */
sess = mem_alloc(sizeof(sess_t));
- sess->id = sess_sys->free_sess_id;
- UT_DULINT_INC(sess_sys->free_sess_id);
-
sess->state = SESS_ACTIVE;
- sess->disconnecting = FALSE;
- sess->msgs_sent = ut_dulint_zero;
- sess->msgs_recv = ut_dulint_zero;
- sess->client_waits = TRUE;
- sess->err_no = 0;
- sess->err_str = NULL;
- sess->error_count = ut_dulint_zero;
-
- sess->big_msg = NULL;
sess->trx = trx_create(sess);
- sess->next_graph_id = 0;
-
UT_LIST_INIT(sess->graphs);
- fold = sess_id_fold(sess->id);
-
- HASH_INSERT(sess_t, hash, sess_sys->hash, fold, sess);
-
- sess->endpoint = endpoint;
- sess->addr_buf = mem_alloc(addr_len);
-
- ut_memcpy(sess->addr_buf, addr_buf, addr_len);
-
- sess->addr_len = addr_len;
-
return(sess);
}
@@ -288,23 +55,11 @@ sess_close(
/*=======*/
sess_t* sess) /* in, own: session object */
{
- ulint fold;
-
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
- ut_ad(sess->disconnecting);
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(sess->trx == NULL);
- ut_ad(sess->refer_count == 0);
-
- fold = ut_fold_dulint(sess->id);
- HASH_DELETE(sess_t, hash, sess_sys->hash, fold, sess);
-/* sess_reply_to_client_rel_kernel(sess); */
-
- if (sess->err_str != NULL) {
- mem_free(sess->err_str);
- }
-
- mem_free(sess->addr_buf);
mem_free(sess);
}
@@ -318,10 +73,10 @@ sess_try_close(
/* out: TRUE if closed */
sess_t* sess) /* in, own: session object */
{
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
-
- if (sess->disconnecting && (UT_LIST_GET_LEN(sess->graphs) == 0)
- && (sess->refer_count == 0)) {
+#endif /* UNIV_SYNC_DEBUG */
+ if (UT_LIST_GET_LEN(sess->graphs) == 0) {
sess_close(sess);
return(TRUE);
@@ -329,259 +84,3 @@ sess_try_close(
return(FALSE);
}
-
-/*************************************************************************
-Initializes the first fields of a message to client. */
-
-void
-sess_srv_msg_init(
-/*==============*/
- sess_t* sess, /* in: session object */
- byte* buf, /* in: message buffer, must be at least of size
- SESS_SRV_MSG_DATA */
- ulint type) /* in: message type */
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- sess->msgs_sent = ut_dulint_add(sess->msgs_sent, 1);
-
- mach_write_to_8(buf + SESS_SRV_MSG_SESS_ID, sess->id);
- mach_write_to_4(buf + SESS_SRV_MSG_TYPE, type);
- mach_write_to_8(buf + SESS_SRV_MSG_NO, sess->msgs_sent);
-
- ut_ad(com_endpoint_get_max_size(sess->endpoint) >= SESS_SRV_MSG_DATA);
-}
-
-/*************************************************************************
-Sends a message to the client. */
-static
-ulint
-sess_srv_msg_send_low(
-/*==================*/
- /* out: 0 if success, else error number */
- sess_t* sess, /* in: session object */
- byte* buf, /* in: message buffer */
- ulint len, /* in: message length */
- ulint rel_ker)/* in: SESS_RELEASE_KERNEL if the kernel mutex should
- be temporarily released in the call; otherwise
- SESS_NOT_RELEASE_KERNEL */
-{
- ulint ret;
-
- ut_ad((rel_ker == SESS_NOT_RELEASE_KERNEL)
- || (rel_ker == SESS_RELEASE_KERNEL));
- ut_ad(mutex_own(&kernel_mutex));
- ut_ad(len <= com_endpoint_get_max_size(sess->endpoint));
- ut_ad(len >= SESS_SRV_MSG_DATA);
-
- if (sess->client_waits == FALSE) {
- sess_error_low(sess, SESS_ERR_EXTRANEOUS_SRV_MSG, NULL);
-
- return(1);
- }
-
- /* The client will now receive an error message: if the session is
- in the error state, we can reset it to the normal state */
-
- if (sess->state == SESS_ERROR) {
- sess->state = SESS_ACTIVE;
- }
-
- /* We reset the client_waits flag to FALSE, regardless of whether the
- message gets delivered to the client or not. This convention makes
- things simpler. */
-
- sess->client_waits = FALSE;
-
- if (rel_ker == SESS_RELEASE_KERNEL) {
-
- mutex_exit(&kernel_mutex);
- }
-
- ret = com_sendto(sess->endpoint, buf, len, sess->addr_buf,
- sess->addr_len);
- if (rel_ker == SESS_RELEASE_KERNEL) {
-
- mutex_enter(&kernel_mutex);
- }
-
- if (ret != 0) {
- sess_error_low(sess, SESS_ERR_REPLY_FAILED, NULL);
- }
-
- return(ret);
-}
-
-/*************************************************************************
-Sends a message to the client. If the session is in the error state, sends
-the error message instead of buf. */
-static
-ulint
-sess_srv_msg_send(
-/*==============*/
- /* out: 0 if success, else error number */
- sess_t* sess, /* in: session object */
- byte* buf, /* in: message buffer */
- ulint len, /* in: message length */
- ulint rel_ker)/* in: SESS_RELEASE_KERNEL if the kernel mutex should
- be temporarily released in the call; otherwise
- SESS_NOT_RELEASE_KERNEL */
-{
- ulint ret;
-
- ut_ad(mutex_own(&kernel_mutex));
-
- if (sess->state == SESS_ERROR) {
-
- sess_srv_msg_send_error(sess);
-
- return(2);
- }
-
- ret = sess_srv_msg_send_low(sess, buf, len, rel_ker);
-
- return(ret);
-}
-
-/*************************************************************************
-Sends a simple message to client. */
-
-void
-sess_srv_msg_send_simple(
-/*=====================*/
- sess_t* sess, /* in: session object */
- ulint type, /* in: message type */
- ulint rel_kernel) /* in: SESS_RELEASE_KERNEL or
- SESS_NOT_RELEASE_KERNEL */
-{
- byte buf[SESS_SRV_MSG_DATA];
-
- ut_ad(mutex_own(&kernel_mutex));
-
- sess_srv_msg_init(sess, buf, type);
-
- sess_srv_msg_send(sess, buf, SESS_SRV_MSG_DATA, rel_kernel);
-}
-
-/*************************************************************************
-Communicates an error message to the client. If sess->client_waits is not
-TRUE, puts the session to error state and does not try to send the error
-message. */
-static
-void
-sess_srv_msg_send_error(
-/*====================*/
- sess_t* sess) /* in: session object */
-{
- ulint err_no;
- byte* err_str;
- ulint err_len;
- ulint max_len;
- byte buf[SESS_ERR_BUF_SIZE];
- ulint ret;
-
- ut_ad(sess->client_waits);
- ut_ad(mutex_own(&kernel_mutex));
- ut_ad(sess->state == SESS_ERROR);
- ut_ad(!UT_LIST_GET_FIRST((sess->trx)->signals));
-
- if (!sess->client_waits) {
- /* Cannot send the error message now: leave the session to
- the error state and send it later */
-
- return;
- }
-
- err_no = sess->err_no;
- err_str = (byte*)sess->err_str;
- err_len = sess->err_len;
-
- max_len = ut_min(SESS_ERR_BUF_SIZE,
- com_endpoint_get_max_size(sess->endpoint));
-
- sess_srv_msg_init(sess, buf, SESS_SRV_ERROR);
-
- if (err_len + SESS_SRV_MSG_DATA > max_len) {
-
- err_len = max_len - SESS_SRV_MSG_DATA;
- }
-
- ut_memcpy(buf + SESS_SRV_MSG_DATA, err_str, err_len);
-
- ret = sess_srv_msg_send_low(sess, buf, SESS_SRV_MSG_DATA + err_len,
- SESS_NOT_RELEASE_KERNEL);
-}
-
-/*************************************************************************
-Copies error info to a session. Sends to the transaction a signal which will
-rollback the latest incomplete SQL statement and then send the error message
-to the client. NOTE: This function will take care of the freeing of the error
-string, thus the caller must supply a copy of the error string. */
-static
-void
-sess_error_low(
-/*===========*/
- sess_t* sess, /* in: session object */
- ulint err_no, /* in: error number */
- char* err_str)/* in, own: error string or NULL;
- NOTE: the function will take care of freeing of the
- string! */
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- UT_DULINT_INC(sess->error_count);
-
- printf("Error string::: %s\n", err_str);
-
- if (sess->state == SESS_ERROR) {
- /* Ignore the error because the session is already in the
- error state */
-
- if (err_str) {
- mem_free(err_str);
- }
-
- return;
- }
-
- sess->err_no = err_no;
-
- if (sess->err_str) {
- mem_free(sess->err_str);
- }
-
- sess->err_str = err_str;
- sess->err_len = ut_strlen(err_str);
- sess->state = SESS_ERROR;
-
- if (sess->big_msg) {
-
- mem_free(sess->big_msg);
- }
-
- /* Send a signal which will roll back the latest incomplete SQL
- statement: the error message will be sent to the client by the error
- handling mechanism after the rollback is completed. */
-
- trx_sig_send(sess->trx, TRX_SIG_ERROR_OCCURRED, TRX_SIG_SELF, FALSE,
- NULL, NULL, NULL);
-}
-
-
-/***************************************************************************
-When a command has been completed, this function sends the message about it
-to the client. */
-
-void
-sess_command_completed_message(
-/*===========================*/
- sess_t* sess, /* in: session */
- byte* msg, /* in: message buffer */
- ulint len) /* in: message data length */
-{
- mutex_enter(&kernel_mutex);
-
- sess_srv_msg_send(sess, msg, SESS_SRV_MSG_DATA + len,
- SESS_RELEASE_KERNEL);
- mutex_exit(&kernel_mutex);
-}
diff --git a/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c
index 534fdf072f1..3697e31050f 100644
--- a/innobase/ut/ut0dbg.c
+++ b/innobase/ut/ut0dbg.c
@@ -18,10 +18,16 @@ ibool ut_dbg_stop_threads = FALSE;
/* Null pointer used to generate memory trap */
ulint* ut_dbg_null_ptr = NULL;
+
const char* ut_dbg_msg_assert_fail =
"InnoDB: Assertion failure in thread %lu in file %s line %lu\n";
const char* ut_dbg_msg_trap =
"InnoDB: We intentionally generate a memory trap.\n"
-"InnoDB: Send a detailed bug report to mysql@lists.mysql.com.\n";
+"InnoDB: Send a detailed bug report to mysql@lists.mysql.com.\n"
+"InnoDB: If you get repeated assertion failures or crashes, even\n"
+"InnoDB: immediately after the mysqld startup, there may be\n"
+"InnoDB: corruption in the InnoDB tablespace. See section 6.1 of\n"
+"InnoDB: http://www.innodb.com/ibman.php about forcing recovery.\n";
+
const char* ut_dbg_msg_stop =
"InnoDB: Thread %lu stopped in file %s line %lu\n";
diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c
index 65229335a09..f7c0e1be9bd 100644
--- a/innobase/ut/ut0mem.c
+++ b/innobase/ut/ut0mem.c
@@ -282,3 +282,27 @@ ut_str_contains(
return(FALSE);
}
+
+/**************************************************************************
+Return a copy of the given string. The returned string must be freed
+using mem_free. */
+
+char*
+ut_strdup(
+/*======*/
+ /* out, own: cnull-terminated string */
+ char* str) /* in: null-terminated string */
+{
+ ulint len;
+ char* copy;
+
+ len = ut_strlen(str);
+
+ copy = mem_alloc(len + 1);
+
+ ut_memcpy(copy, str, len);
+
+ copy[len] = 0;
+
+ return(copy);
+}
diff --git a/isam/isamchk.c b/isam/isamchk.c
index 4e7ab7ec854..8fa6b7ad4c0 100644
--- a/isam/isamchk.c
+++ b/isam/isamchk.c
@@ -3413,6 +3413,6 @@ static int update_state_info( N_INFO *info, uint update)
return 0;
}
err:
- print_error("%d when updateing keyfile",my_errno);
+ print_error("%d when updating keyfile",my_errno);
return 1;
}
diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h
index 5ce0e021782..9fc8e67df27 100644
--- a/libmysql/client_settings.h
+++ b/libmysql/client_settings.h
@@ -22,7 +22,6 @@ extern my_string mysql_unix_port;
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
sig_handler pipe_sig_handler(int sig __attribute__((unused)));
-my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list, my_bool skip_free);
void read_user_name(char *name);
my_bool send_file_to_server(MYSQL *mysql, const char *filename);
@@ -57,7 +56,7 @@ MYSQL_DATA * cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
int cli_stmt_execute(MYSQL_STMT *stmt);
MYSQL_DATA * cli_read_binary_rows(MYSQL_STMT *stmt);
int cli_unbuffered_fetch(MYSQL *mysql, char **row);
-const char * cli_read_statistic(MYSQL *mysql);
+const char * cli_read_statistics(MYSQL *mysql);
int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd);
#ifdef EMBEDDED_LIBRARY
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 569267ddb37..ad93c1b8f9e 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -52,9 +52,10 @@ const char *client_errors[]=
"Error connecting to master:",
"SSL connection error",
"Malformed packet",
+ "This client library is licensed only for use with MySQL servers having '%s' license",
"Invalid use of null pointer",
"Statement not prepared",
- "Not all parameters data supplied",
+ "Parameters data was not supplied",
"Data truncated",
"No parameters exists in the statement",
"Invalid parameter number",
@@ -72,7 +73,9 @@ const char *client_errors[]=
"Can't open shared memory. Can't send the request event to server (%lu)",
"Wrong or unknown protocol",
"Invalid connection handle",
- "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)"
+ "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
+ "Row retrieval was cancelled by mysql_stmt_close() call",
+ "Attempt to read column without prior row fetch"
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
@@ -108,9 +111,10 @@ const char *client_errors[]=
"Error connecting to master:",
"SSL connection error",
"Malformed packet",
+ "This client library is licensed only for use with MySQL servers having '%s' license",
"Invalid use of null pointer",
"Statement not prepared",
- "Not all parameters data supplied",
+ "Parameters data was not supplied",
"Data truncated",
"No parameters exists in the statement",
"Invalid parameter number",
@@ -128,7 +132,9 @@ const char *client_errors[]=
"Can't open shared memory. Can't send the request event to server (%lu)",
"Wrong or unknown protocol",
"Invalid connection handle",
- "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)"
+ "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
+ "Row retrieval was cancelled by mysql_stmt_close() call",
+ "Attempt to read column without prior row fetch"
};
#else /* ENGLISH */
@@ -162,6 +168,7 @@ const char *client_errors[]=
"Error connecting to master:",
"SSL connection error",
"Malformed packet",
+ "This client library is licensed only for use with MySQL servers having '%s' license",
"Invalid use of null pointer",
"Statement not prepared",
"Not all parameters data supplied",
@@ -182,7 +189,9 @@ const char *client_errors[]=
"Can't open shared memory. Can't send the request event to server (%lu)",
"Wrong or unknown protocol",
"Invalid connection handle",
- "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)"
+ "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
+ "Row retrieval was cancelled by mysql_stmt_close() call",
+ "Attempt to read column without prior row fetch"
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index e88e34f8925..0a93fe60990 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -89,7 +89,6 @@ static void append_wild(char *to,char *end,const char *wild);
sig_handler pipe_sig_handler(int sig);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
const char *from, ulong length);
-my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list, my_bool skip_free);
static my_bool mysql_client_init= 0;
static my_bool org_my_init_done= 0;
@@ -604,6 +603,57 @@ mysql_connect(MYSQL *mysql,const char *host,
#endif
+#ifdef CHECK_LICENSE
+/*
+ Check server side variable 'license'.
+ If the variable does not exist or does not contain 'Commercial',
+ we're talking to non-commercial server from commercial client.
+ SYNOPSIS
+ check_license()
+ RETURN VALUE
+ 0 success
+ !0 network error or the server is not commercial.
+ Error code is saved in mysql->net.last_errno.
+*/
+
+static int check_license(MYSQL *mysql)
+{
+ MYSQL_ROW row;
+ MYSQL_RES *res;
+ NET *net= &mysql->net;
+ static const char query[]= "SELECT @@license";
+ static const char required_license[]= LICENSE;
+
+ if (mysql_real_query(mysql, query, sizeof(query)-1))
+ {
+ if (net->last_errno == ER_UNKNOWN_SYSTEM_VARIABLE)
+ {
+ net->last_errno= CR_WRONG_LICENSE;
+ sprintf(net->last_error, ER(net->last_errno), required_license);
+ }
+ return 1;
+ }
+ if (!(res= mysql_use_result(mysql)))
+ return 1;
+ row= mysql_fetch_row(res);
+ /*
+ If no rows in result set, or column value is NULL (none of these
+ two is ever true for server variables now), or column value
+ mismatch, set wrong license error.
+ */
+ if (!net->last_errno &&
+ (!row || !row[0] ||
+ strncmp(row[0], required_license, sizeof(required_license))))
+ {
+ net->last_errno= CR_WRONG_LICENSE;
+ sprintf(net->last_error, ER(net->last_errno), required_license);
+ }
+ mysql_free_result(res);
+ return net->last_errno;
+}
+#endif /* CHECK_LICENSE */
+
+
/**************************************************************************
Change user and database
**************************************************************************/
@@ -639,6 +689,7 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
return 0;
}
+
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db)
{
@@ -867,6 +918,7 @@ STDCALL mysql_set_master(MYSQL* mysql, const char* host,
return 0;
}
+
int
STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
unsigned int port,
@@ -988,6 +1040,7 @@ mysql_list_tables(MYSQL *mysql, const char *wild)
DBUG_RETURN (mysql_store_result(mysql));
}
+
MYSQL_FIELD *cli_list_fields(MYSQL *mysql)
{
MYSQL_DATA *query;
@@ -1063,6 +1116,7 @@ mysql_list_processes(MYSQL *mysql)
DBUG_RETURN(mysql_store_result(mysql));
}
+
#ifdef USE_OLD_FUNCTIONS
int STDCALL
mysql_create_db(MYSQL *mysql, const char *db)
@@ -1100,6 +1154,7 @@ mysql_refresh(MYSQL *mysql,uint options)
DBUG_RETURN(simple_command(mysql,COM_REFRESH,(char*) bits,1,0));
}
+
int STDCALL
mysql_kill(MYSQL *mysql,ulong pid)
{
@@ -1127,7 +1182,8 @@ mysql_dump_debug_info(MYSQL *mysql)
DBUG_RETURN(simple_command(mysql,COM_DEBUG,0,0,0));
}
-const char *cli_read_statistic(MYSQL *mysql)
+
+const char *cli_read_statistics(MYSQL *mysql)
{
mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */
if (!mysql->net.read_pos[0])
@@ -1140,13 +1196,14 @@ const char *cli_read_statistic(MYSQL *mysql)
return (char*) mysql->net.read_pos;
}
+
const char * STDCALL
mysql_stat(MYSQL *mysql)
{
DBUG_ENTER("mysql_stat");
if (simple_command(mysql,COM_STATISTICS,0,0,0))
return mysql->net.last_error;
- DBUG_RETURN((*mysql->methods->read_statistic)(mysql));
+ DBUG_RETURN((*mysql->methods->read_statistics)(mysql));
}
@@ -1545,21 +1602,6 @@ void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode,
}
-/*
- Set the internal error message to mysql handler
-*/
-
-static void set_mysql_error(MYSQL * mysql, int errcode, const char *sqlstate)
-{
- DBUG_ENTER("set_mysql_error");
- DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode)));
- DBUG_ASSERT(mysql != 0);
-
- mysql->net.last_errno= errcode;
- strmov(mysql->net.last_error, ER(errcode));
- strmov(mysql->net.sqlstate, sqlstate);
-}
-
/*
Reallocate the NET package to be at least of 'length' bytes
@@ -1592,6 +1634,10 @@ static my_bool my_realloc_str(NET *net, ulong length)
Prepare related implementations
********************************************************************/
+static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row);
+static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row);
+static int stmt_read_row_no_data(MYSQL_STMT *stmt, unsigned char **row);
+
/*
Read the prepared statement results ..
@@ -1607,13 +1653,12 @@ static my_bool my_realloc_str(NET *net, ulong length)
my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
{
uchar *pos;
- uint field_count;
- ulong length, param_count;
+ uint field_count, param_count;
MYSQL_DATA *fields_data;
DBUG_ENTER("read_prepare_result");
mysql= mysql->last_used_con;
- if ((length= net_safe_read(mysql)) == packet_error)
+ if (net_safe_read(mysql) == packet_error)
DBUG_RETURN(1);
pos= (uchar*) mysql->net.read_pos;
@@ -1640,76 +1685,168 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
DBUG_RETURN(0);
}
+#ifdef HAVE_DEPRECATED_411_API
+MYSQL_STMT * STDCALL mysql_prepare(MYSQL *mysql, const char *query,
+ unsigned long query_length)
+{
+ MYSQL_STMT *stmt;
+ DBUG_ENTER("mysql_prepare");
+
+ stmt= mysql_stmt_init(mysql);
+ if (stmt && mysql_stmt_prepare(stmt, query, query_length))
+ {
+ mysql_stmt_close(stmt);
+ DBUG_RETURN(0);
+ }
+ DBUG_RETURN(stmt);
+}
+#endif
/*
- Prepare the query and return the new statement handle to
- caller.
+ Allocate memory and init prepared statement structure
+ SYNOPSIS
+ mysql_stmt_init()
+ mysql connection handle
- Also update the total parameter count along with resultset
- metadata information by reading from server
+ RETURN VALUE
+ statement structure upon success and NULL if out of
+ memory
*/
-
-MYSQL_STMT *STDCALL
-mysql_prepare(MYSQL *mysql, const char *query, ulong length)
+MYSQL_STMT * STDCALL
+mysql_stmt_init(MYSQL *mysql)
{
- MYSQL_STMT *stmt;
- DBUG_ENTER("mysql_prepare");
- DBUG_ASSERT(mysql != 0);
+ MYSQL_STMT *stmt;
+ DBUG_ENTER("mysql_stmt_init");
if (!(stmt= (MYSQL_STMT *) my_malloc(sizeof(MYSQL_STMT),
- MYF(MY_WME | MY_ZEROFILL))) ||
- !(stmt->query= my_strdup_with_length((byte *) query, length, MYF(0))))
+ MYF(MY_WME | MY_ZEROFILL))))
{
- my_free((gptr) stmt, MYF(MY_ALLOW_ZERO_PTR));
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(0);
}
+
+ init_alloc_root(&stmt->mem_root, 2048, 2048);
+ mysql->stmts= list_add(mysql->stmts, &stmt->list);
+ stmt->list.data= stmt;
+ stmt->state= MYSQL_STMT_INIT_DONE;
+ stmt->mysql= mysql;
+ stmt->read_row_func= stmt_read_row_no_data;
+ /* The rest of statement members was bzeroed inside malloc */
+
+ DBUG_RETURN(stmt);
+}
+
+/*
+ Prepare server side statement with query:
+ SYNOPSIS
+ mysql_stmt_prepare()
+ query statement to prepare
+ length statement length
+
+ DESCRIPTION
+ - if this is a re-prepare of the statement, first close previous data
+ structure on the server and free old statement data
+ - send the query to server and get back number of placeholders,
+ number of columns in result set (if any), and result set metadata.
+ At the same time allocate memory for input and output parameters
+ to have less checks in mysql_stmt_bind_{param, result}.
+
+ RETURN VALUES
+ 0 success
+ !0 error
+*/
+
+
+int STDCALL
+mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
+{
+ MYSQL *mysql= stmt->mysql;
+ DBUG_ENTER("mysql_stmt_prepare");
+
+ if (!mysql)
+ {
+ /* mysql can be reset in mysql_close called from mysql_reconnect */
+ set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
+ DBUG_RETURN(1);
+ }
+
+ if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
+ {
+ /* This is second prepare with another statement */
+ char buff[4];
+
+ mysql_stmt_free_result(stmt);
+ /*
+ These members must be reset for API to
+ function in case of error or misuse.
+ */
+ stmt->bind_param_done= stmt->bind_result_done= FALSE;
+ stmt->param_count= stmt->field_count= 0;
+ stmt->last_errno= 0;
+ stmt->last_error[0]= '\0';
+ free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
+
+ int4store(buff, stmt->stmt_id);
+ /*
+ If there was a 'use' result from another statement, or from
+ mysql_use_result it won't be freed in mysql_stmt_free_result and
+ we should get 'Commands out of sync' here.
+ */
+ if (simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1))
+ {
+ set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
+ mysql->net.sqlstate);
+ DBUG_RETURN(1);
+ }
+ stmt->state= MYSQL_STMT_INIT_DONE;
+ }
+
if (simple_command(mysql, COM_PREPARE, query, length, 1))
{
- stmt_close(stmt, 1, 0);
- DBUG_RETURN(0);
+ set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
+ mysql->net.sqlstate);
+ DBUG_RETURN(1);
}
- init_alloc_root(&stmt->mem_root,8192,0);
if ((*mysql->methods->read_prepare_result)(mysql, stmt))
{
- stmt_close(stmt, 1, 0);
- DBUG_RETURN(0);
+ set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
+ mysql->net.sqlstate);
+ DBUG_RETURN(1);
}
+ /*
+ alloc_root will return valid address even in case param_count
+ and field_count are zero. Thus we should never rely on stmt->bind
+ or stmt->params when checking for existence of placeholders or
+ result set.
+ */
if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
sizeof(MYSQL_BIND)*
(stmt->param_count +
stmt->field_count))))
{
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
- DBUG_RETURN(0);
+ DBUG_RETURN(1);
}
stmt->bind= stmt->params + stmt->param_count;
- stmt->state= MY_ST_PREPARE;
- stmt->mysql= mysql;
- mysql->stmts= list_add(mysql->stmts, &stmt->list);
- mysql->status= MYSQL_STATUS_READY;
- stmt->list.data= stmt;
+ stmt->state= MYSQL_STMT_PREPARE_DONE;
DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
- DBUG_RETURN(stmt);
+ DBUG_RETURN(0);
}
/*
Get the execute query meta information for non-select
- statements (on demand).
+ statements.
*/
-unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
+static unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
{
MYSQL_FIELD *fields, *field, *end;
MEM_ROOT *alloc= &stmt->mem_root;
MYSQL *mysql= stmt->mysql->last_used_con;
- if (stmt->state != MY_ST_EXECUTE || !mysql->field_count)
- return 0;
-
stmt->field_count= mysql->field_count;
/*
@@ -1750,25 +1887,30 @@ unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
*/
MYSQL_RES * STDCALL
-mysql_get_metadata(MYSQL_STMT *stmt)
+mysql_stmt_result_metadata(MYSQL_STMT *stmt)
{
MYSQL_RES *result;
- DBUG_ENTER("mysql_get_metadata");
+ DBUG_ENTER("mysql_stmt_result_metadata");
- if (!stmt->field_count || !stmt->fields)
+ /*
+ stmt->fields is only defined if stmt->field_count is not null;
+ stmt->field_count is initialized in prepare.
+ */
+ if (!stmt->field_count)
+ DBUG_RETURN(0);
+
+ if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result),
+ MYF(MY_WME | MY_ZEROFILL))))
{
- if (!alloc_stmt_fields(stmt))
- DBUG_RETURN(0);
- }
- if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
- sizeof(ulong)*stmt->field_count,
- MYF(MY_WME | MY_ZEROFILL))))
- return 0;
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
+ DBUG_RETURN(0);
+ }
- result->methods= stmt->mysql->methods;
- result->eof=1; /* Marker for buffered */
+ result->methods= stmt->mysql->methods;
+ result->eof= 1; /* Marker for buffered */
result->fields= stmt->fields;
result->field_count= stmt->field_count;
+ /* The rest of members of 'result' was bzeroed inside malloc */
DBUG_RETURN(result);
}
@@ -1778,9 +1920,9 @@ mysql_get_metadata(MYSQL_STMT *stmt)
*/
MYSQL_RES * STDCALL
-mysql_param_result(MYSQL_STMT *stmt)
+mysql_stmt_param_metadata(MYSQL_STMT *stmt)
{
- DBUG_ENTER("mysql_param_result");
+ DBUG_ENTER("mysql_stmt_param_metadata");
if (!stmt->param_count)
DBUG_RETURN(0);
@@ -1962,11 +2104,9 @@ static void store_param_null(NET *net, MYSQL_BIND *param)
client application
*/
-
static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
{
- MYSQL *mysql= stmt->mysql;
- NET *net = &mysql->net;
+ NET *net= &stmt->mysql->net;
DBUG_ENTER("store_param");
DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %lu is_null: %d",
param->buffer_type,
@@ -2032,6 +2172,12 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
uint null_count;
my_bool result;
+ if (!stmt->bind_param_done)
+ {
+ set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate);
+ DBUG_RETURN(1);
+ }
+
net_clear(net); /* Sets net->write_pos */
/* Reserve place for null-marker bytes */
null_count= (stmt->param_count+7) /8;
@@ -2066,7 +2212,6 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(1);
}
- net->write_pos= net->buff; /* Reset for net_write() */
result= execute(stmt, param_data, length);
stmt->send_types_to_server=0;
my_free(param_data, MYF(MY_WME));
@@ -2076,21 +2221,145 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
}
/*
+ Read one row from buffered result set. Result set is created by prior
+ call to mysql_stmt_store_result().
+ SYNOPSIS
+ stmt_read_row_buffered()
+
+ RETURN VALUE
+ 0 - success; *row is set to valid row pointer (row data
+ is stored in result set buffer)
+ MYSQL_NO_DATA - end of result set. *row is set to NULL
+*/
+
+static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row)
+{
+ MYSQL_RES *result= stmt->result;
+
+ if (result && result->data_cursor)
+ {
+ *row= (uchar *) result->data_cursor->data;
+ result->data_cursor= result->data_cursor->next;
+ return 0;
+ }
+ *row= 0;
+ return MYSQL_NO_DATA;
+}
+
+/*
+ Read one row from network: unbuffered non-cursor fetch.
+ If last row was read, or error occured, erase this statement
+ from record pointing to object unbuffered fetch is performed from.
+
+ SYNOPSIS
+ stmt_read_row_unbuffered()
+ stmt statement handle
+ row pointer to write pointer to row data;
+
+ RETURN VALUE
+ 0 - success; *row contains valid address of a row;
+ row data is stored in network buffer
+ 1 - error; error code is written to
+ stmt->last_{errno,error}; *row is not changed
+ MYSQL_NO_DATA - end of file was read from network;
+ *row is to NULL
+*/
+
+static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
+{
+ int rc= 1;
+ MYSQL *mysql= stmt->mysql;
+ /*
+ This function won't be called if stmt->field_count is zero
+ or execution wasn't done: this is ensured by mysql_stmt_execute.
+ */
+ if (!mysql)
+ {
+ set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
+ return 1;
+ }
+ if (mysql->status != MYSQL_STATUS_GET_RESULT)
+ {
+ set_stmt_error(stmt, stmt->unbuffered_fetch_cancelled ?
+ CR_FETCH_CANCELLED : CR_COMMANDS_OUT_OF_SYNC,
+ unknown_sqlstate);
+ goto error;
+ }
+ if ((*mysql->methods->unbuffered_fetch)(mysql, (char**) row))
+ {
+ set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
+ mysql->net.sqlstate);
+ goto error;
+ }
+ if (!*row)
+ {
+ mysql->status= MYSQL_STATUS_READY;
+ rc= MYSQL_NO_DATA;
+ goto error;
+ }
+ return 0;
+error:
+ if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
+ mysql->unbuffered_fetch_owner= 0;
+ return rc;
+}
+
+/*
+ Default read row function to not SIGSEGV in client in
+ case of wrong sequence of API calls.
+*/
+
+static int
+stmt_read_row_no_data(MYSQL_STMT *stmt __attribute__((unused)),
+ unsigned char **row __attribute__((unused)))
+{
+ if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
+ {
+ set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate);
+ return 1;
+ }
+ return MYSQL_NO_DATA;
+}
+
+/*
Execute the prepared query
*/
-int STDCALL mysql_execute(MYSQL_STMT *stmt)
+int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
{
- DBUG_ENTER("mysql_execute");
+ MYSQL *mysql= stmt->mysql;
+ DBUG_ENTER("mysql_stmt_execute");
+
+ if (!mysql)
+ {
+ set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
+ DBUG_RETURN(1);
+ }
- if ((*stmt->mysql->methods->stmt_execute)(stmt))
+ mysql_stmt_free_result(stmt);
+ /*
+ No need to check for stmt->state: if the statement wasn't
+ prepared we'll get 'unknown statemenet handler' error from server.
+ */
+ if (mysql->methods->stmt_execute(stmt))
DBUG_RETURN(1);
+ if (!stmt->field_count && mysql->field_count)
+ {
+ /*
+ This is 'SHOW'/'EXPLAIN'-like query. Current implementation of
+ prepared statements can't send result set metadata for this queries
+ on prepare stage. Read it now.
+ */
+ alloc_stmt_fields(stmt);
+ }
- stmt->state= MY_ST_EXECUTE;
- mysql_free_result(stmt->result);
- stmt->result= (MYSQL_RES *)0;
- stmt->result_buffered= 0;
- stmt->current_row= 0;
+ stmt->state= MYSQL_STMT_EXECUTE_DONE;
+ if (stmt->field_count)
+ {
+ stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
+ stmt->unbuffered_fetch_cancelled= FALSE;
+ stmt->read_row_func= stmt_read_row_unbuffered;
+ }
DBUG_RETURN(0);
}
@@ -2099,9 +2368,9 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt)
Return total parameters count in the statement
*/
-ulong STDCALL mysql_param_count(MYSQL_STMT * stmt)
+ulong STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt)
{
- DBUG_ENTER("mysql_param_count");
+ DBUG_ENTER("mysql_stmt_param_count");
DBUG_RETURN(stmt->param_count);
}
@@ -2122,11 +2391,21 @@ static my_bool int_is_null_false= 0;
Setup the parameter data buffers from application
*/
-my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
+my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
{
uint count=0;
MYSQL_BIND *param, *end;
- DBUG_ENTER("mysql_bind_param");
+ DBUG_ENTER("mysql_stmt_bind_param");
+
+ if (!stmt->param_count)
+ {
+ if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
+ {
+ set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate);
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+ }
/* Allocated on prepare */
memcpy((char*) stmt->params, (char*) bind,
@@ -2139,13 +2418,6 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
param->param_number= count++;
param->long_data_used= 0;
- /*
- If param->length is not given, change it to point to buffer_length.
- This way we can always use *param->length to get the length of data
- */
- if (!param->length)
- param->length= &param->buffer_length;
-
/* If param->is_null is not set, then the value can never be NULL */
if (!param->is_null)
param->is_null= &int_is_null_false;
@@ -2212,10 +2484,16 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
param->buffer_type, count);
DBUG_RETURN(1);
}
+ /*
+ If param->length is not given, change it to point to buffer_length.
+ This way we can always use *param->length to get the length of data
+ */
+ if (!param->length)
+ param->length= &param->buffer_length;
}
/* We have to send/resendtype information to MySQL */
- stmt->send_types_to_server= 1;
- stmt->param_buffers= 1;
+ stmt->send_types_to_server= TRUE;
+ stmt->bind_param_done= TRUE;
DBUG_RETURN(0);
}
@@ -2228,7 +2506,7 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
Send long data in pieces to the server
SYNOPSIS
- mysql_send_long_data()
+ mysql_stmt_send_long_data()
stmt Statement handler
param_number Parameter number (0 - N-1)
data Data to send to server
@@ -2241,14 +2519,24 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
my_bool STDCALL
-mysql_send_long_data(MYSQL_STMT *stmt, uint param_number,
+mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
const char *data, ulong length)
{
MYSQL_BIND *param;
- DBUG_ENTER("mysql_send_long_data");
+ DBUG_ENTER("mysql_stmt_send_long_data");
DBUG_ASSERT(stmt != 0);
DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld",
param_number, data, length));
+
+ /*
+ We only need to check for stmt->param_count, if it's not null
+ prepare was done.
+ */
+ if (param_number >= stmt->param_count)
+ {
+ set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate);
+ DBUG_RETURN(1);
+ }
param= stmt->params+param_number;
if (param->buffer_type < MYSQL_TYPE_TINY_BLOB ||
@@ -2811,17 +3099,28 @@ static void fetch_result_str(MYSQL_BIND *param, uchar **row)
Setup the bind buffers for resultset processing
*/
-my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
+my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
{
MYSQL_BIND *param, *end;
ulong bind_count;
uint param_count= 0;
- DBUG_ENTER("mysql_bind_result");
+ DBUG_ENTER("mysql_stmt_bind_result");
DBUG_ASSERT(stmt != 0);
- if (!(bind_count= stmt->field_count) &&
- !(bind_count= alloc_stmt_fields(stmt)))
+ if (!stmt->field_count)
+ {
+ if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
+ {
+ set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate);
+ }
DBUG_RETURN(0);
+ }
+ bind_count= stmt->field_count;
+
+ /*
+ We only need to check that stmt->field_count - if it is not null
+ stmt->bind was initialized in mysql_stmt_prepare
+ */
memcpy((char*) stmt->bind, (char*) bind,
sizeof(MYSQL_BIND)*bind_count);
@@ -2830,7 +3129,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
{
/*
Set param->is_null to point to a dummy variable if it's not set.
- This is to make the excute code easier
+ This is to make the execute code easier
*/
if (!param->is_null)
param->is_null= &param->internal_is_null;
@@ -2902,7 +3201,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
DBUG_RETURN(1);
}
}
- stmt->res_buffers= 1;
+ stmt->bind_result_done= TRUE;
DBUG_RETURN(0);
}
@@ -2916,9 +3215,18 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
MYSQL_BIND *bind, *end;
MYSQL_FIELD *field, *field_end;
uchar *null_ptr, bit;
+ /*
+ Precondition: if stmt->field_count is zero or row is NULL, read_row_*
+ function must return no data.
+ */
+ DBUG_ASSERT(stmt->field_count);
+ DBUG_ASSERT(row);
- if (!row || !stmt->res_buffers)
+ if (!stmt->bind_result_done)
+ {
+ /* If output parameters were not bound we should just return success */
return 0;
+ }
null_ptr= row;
row+= (stmt->field_count+9)/8; /* skip null bits */
@@ -2965,59 +3273,24 @@ int cli_unbuffered_fetch(MYSQL *mysql, char **row)
Fetch and return row data to bound buffers, if any
*/
-int STDCALL mysql_fetch(MYSQL_STMT *stmt)
+int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
{
- MYSQL *mysql= stmt->mysql;
+ int rc;
uchar *row;
- DBUG_ENTER("mysql_fetch");
+ DBUG_ENTER("mysql_stmt_fetch");
- stmt->last_fetched_column= 0; /* reset */
- if (stmt->result_buffered) /* buffered */
+ if ((rc= (*stmt->read_row_func)(stmt, &row)) ||
+ (rc= stmt_fetch_row(stmt, row)))
{
- MYSQL_RES *res;
-
- if (!(res= stmt->result))
- goto no_data;
-
- if (!res->data_cursor)
- {
- stmt->current_row= 0;
- goto no_data;
- }
- row= (uchar *)res->data_cursor->data;
- res->data_cursor= res->data_cursor->next;
+ stmt->state= MYSQL_STMT_PREPARE_DONE; /* XXX: this is buggy */
+ stmt->read_row_func= stmt_read_row_no_data;
}
- else /* un-buffered */
+ else
{
- if (mysql->status != MYSQL_STATUS_GET_RESULT)
- {
- if (!stmt->field_count)
- goto no_data;
-
- set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
- DBUG_RETURN(1);
- }
-
- if ((*mysql->methods->unbuffered_fetch)(mysql, (char**) &row))
- {
- set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
- mysql->net.sqlstate);
- DBUG_RETURN(1);
- }
- if (!row)
- {
- mysql->status= MYSQL_STATUS_READY;
- stmt->current_row= 0;
- goto no_data;
- }
+ /* This is to know in mysql_stmt_fetch_column that data was fetched */
+ stmt->state= MYSQL_STMT_FETCH_DONE;
}
-
- stmt->current_row= row;
- DBUG_RETURN(stmt_fetch_row(stmt, row));
-
-no_data:
- DBUG_PRINT("info", ("end of data"));
- DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
+ DBUG_RETURN(rc);
}
@@ -3025,10 +3298,10 @@ no_data:
Fetch data for one specified column data
SYNOPSIS
- mysql_fetch_column()
+ mysql_stmt_fetch_column()
stmt Prepared statement handler
bind Where data should be placed. Should be filled in as
- when calling mysql_bind_result()
+ when calling mysql_stmt_bind_result()
column Column to fetch (first column is 0)
ulong offset Offset in result data (to fetch blob in pieces)
This is normally 0
@@ -3037,14 +3310,23 @@ no_data:
1 error
*/
-int STDCALL mysql_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
- uint column, ulong offset)
+int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
+ uint column, ulong offset)
{
MYSQL_BIND *param= stmt->bind+column;
- DBUG_ENTER("mysql_fetch_column");
+ DBUG_ENTER("mysql_stmt_fetch_column");
+
+ if ((int) stmt->state < (int) MYSQL_STMT_FETCH_DONE)
+ {
+ set_stmt_error(stmt, CR_NO_DATA, unknown_sqlstate);
+ return 1;
+ }
+ if (column >= stmt->field_count)
+ {
+ set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate);
+ DBUG_RETURN(1);
+ }
- if (!stmt->current_row)
- goto no_data;
if (param->null_field)
{
@@ -3065,10 +3347,6 @@ int STDCALL mysql_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
fetch_results(bind, field, &row);
}
DBUG_RETURN(0);
-
-no_data:
- DBUG_PRINT("info", ("end of data"));
- DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
}
@@ -3084,7 +3362,7 @@ MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt)
MYSQL_DATA *result;
MYSQL_ROWS *cur, **prev_ptr;
NET *net = &mysql->net;
- DBUG_ENTER("read_binary_rows");
+ DBUG_ENTER("cli_read_binary_rows");
mysql= mysql->last_used_con;
if ((pkt_len= net_safe_read(mysql)) == packet_error)
@@ -3100,8 +3378,7 @@ MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt)
if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
MYF(MY_WME | MY_ZEROFILL))))
{
- set_stmt_errmsg(stmt, ER(CR_OUT_OF_MEMORY), CR_OUT_OF_MEMORY,
- unknown_sqlstate);
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(0);
}
init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
@@ -3117,8 +3394,7 @@ MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt)
!(cur->data= ((MYSQL_ROW) alloc_root(&result->alloc, pkt_len))))
{
free_rows(result);
- set_stmt_errmsg(stmt, ER(CR_OUT_OF_MEMORY), CR_OUT_OF_MEMORY,
- unknown_sqlstate);
+ set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(0);
}
*prev_ptr= cur;
@@ -3156,34 +3432,38 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
if (!stmt->field_count)
DBUG_RETURN(0);
- if (mysql->status != MYSQL_STATUS_GET_RESULT)
+ if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE ||
+ mysql->status != MYSQL_STATUS_GET_RESULT)
{
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(1);
}
- mysql->status= MYSQL_STATUS_READY; /* server is ready */
- if (!(result= (MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
- sizeof(ulong) *
- stmt->field_count),
+ if (!(result= (MYSQL_RES*) my_malloc(sizeof(MYSQL_RES),
MYF(MY_WME | MY_ZEROFILL))))
{
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(1);
}
result->methods= mysql->methods;
- stmt->result_buffered= 1;
- if (!(result->data= (*stmt->mysql->methods->read_binary_rows)(stmt)))
+ if ((result->data= (*mysql->methods->read_binary_rows)(stmt)))
+ {
+ result->row_count= result->data->rows;
+ result->data_cursor= result->data->data;
+ }
+ else if (stmt->last_errno)
{
my_free((gptr) result,MYF(0));
- DBUG_RETURN(0);
+ DBUG_RETURN(1);
}
- mysql->affected_rows= result->row_count= result->data->rows;
- stmt->affected_rows= result->row_count;
- result->data_cursor= result->data->data;
+ mysql->affected_rows= stmt->affected_rows= result->row_count;
result->fields= stmt->fields;
result->field_count= stmt->field_count;
+ /* The rest of MYSQL_RES members were bzeroed inside my_malloc */
stmt->result= result;
- DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_fetch() */
+ stmt->read_row_func= stmt_read_row_buffered;
+ mysql->unbuffered_fetch_owner= 0; /* set in stmt_execute */
+ mysql->status= MYSQL_STATUS_READY; /* server is ready */
+ DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_stmt_fetch() */
}
@@ -3267,6 +3547,40 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
DBUG_RETURN(0);
}
+my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
+{
+ DBUG_ENTER("mysql_stmt_free_result");
+
+ DBUG_ASSERT(stmt != 0);
+
+ if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
+ {
+ MYSQL *mysql= stmt->mysql;
+
+ if (stmt->result)
+ {
+ /* Result buffered */
+ mysql_free_result(stmt->result);
+ stmt->result= 0;
+ }
+ else if (mysql && stmt->field_count
+ && (int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
+ {
+ if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
+ mysql->unbuffered_fetch_owner= 0;
+ if (mysql->status != MYSQL_STATUS_READY)
+ {
+ /* There is a result set and it belongs to this statement */
+ flush_use_result(mysql);
+ mysql->status= MYSQL_STATUS_READY;
+ }
+ }
+ stmt->state= MYSQL_STMT_PREPARE_DONE;
+ stmt->read_row_func= stmt_read_row_no_data;
+ }
+ DBUG_RETURN(0);
+}
+
/********************************************************************
statement error handling and close
*********************************************************************/
@@ -3277,82 +3591,53 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
SYNOPSIS
mysql_stmt_close()
stmt Statement handle
- skip_list Flag to indicate delete from list or not
+
RETURN VALUES
0 ok
1 error
*/
-my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
-{
- MYSQL *mysql;
- DBUG_ENTER("mysql_stmt_free_result");
-
- DBUG_ASSERT(stmt != 0);
-
- mysql= stmt->mysql;
- if (mysql->status != MYSQL_STATUS_READY)
- {
- /* Clear the current execution status */
- DBUG_PRINT("warning",("Not all packets read, clearing them"));
- for (;;)
- {
- ulong pkt_len;
- if ((pkt_len= net_safe_read(mysql)) == packet_error)
- break;
- if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
- break;
- }
- mysql->status= MYSQL_STATUS_READY;
- }
- mysql_free_result(stmt->result);
- stmt->result= 0;
- stmt->result_buffered= 0;
- stmt->current_row= 0;
- DBUG_RETURN(0);
-}
-
-
-my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list, my_bool skip_free)
+my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
{
- MYSQL *mysql;
+ MYSQL *mysql= stmt->mysql;
+ int rc= 0;
DBUG_ENTER("mysql_stmt_close");
- DBUG_ASSERT(stmt != 0);
-
- if (!(mysql= stmt->mysql))
- {
- if (!skip_free)
- my_free((gptr) stmt, MYF(MY_WME));
- DBUG_RETURN(0);
- }
- mysql_stmt_free_result(stmt);
- if (stmt->state == MY_ST_PREPARE || stmt->state == MY_ST_EXECUTE)
+ mysql_free_result(stmt->result); /* if result is buffered */
+ free_root(&stmt->mem_root, MYF(0));
+
+ if (mysql)
{
- char buff[4];
- int4store(buff, stmt->stmt_id);
- if (skip_free || simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1))
+ mysql->stmts= list_delete(mysql->stmts, &stmt->list);
+ if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
{
- set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
- mysql->net.sqlstate);
- stmt->mysql= NULL; /* connection isn't valid anymore */
- DBUG_RETURN(1);
+ char buff[4];
+
+ if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
+ mysql->unbuffered_fetch_owner= 0;
+ if (mysql->status != MYSQL_STATUS_READY)
+ {
+ /*
+ Flush result set of the connection. If it does not belong
+ to this statement, set a warning.
+ */
+ flush_use_result(mysql);
+ if (mysql->unbuffered_fetch_owner)
+ *mysql->unbuffered_fetch_owner= TRUE;
+ mysql->status= MYSQL_STATUS_READY;
+ }
+ int4store(buff, stmt->stmt_id);
+ if ((rc= simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1)))
+ {
+ set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
+ mysql->net.sqlstate);
+ }
}
}
- stmt->field_count= 0;
- free_root(&stmt->mem_root, MYF(0));
- if (!skip_list)
- mysql->stmts= list_delete(mysql->stmts, &stmt->list);
- mysql->status= MYSQL_STATUS_READY;
- my_free((gptr) stmt->query, MYF(MY_WME));
- my_free((gptr) stmt, MYF(MY_WME));
- DBUG_RETURN(0);
-}
+ my_free((gptr) stmt, MYF(MY_WME));
-my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
-{
- return stmt_close(stmt, 0, 0);
+ DBUG_RETURN(test(rc));
}
/*
@@ -3365,6 +3650,10 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
MYSQL *mysql;
DBUG_ENTER("mysql_stmt_reset");
DBUG_ASSERT(stmt != 0);
+
+ /* If statement hasnt been prepared there is nothing to reset */
+ if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
+ DBUG_RETURN(0);
mysql= stmt->mysql->last_used_con;
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 470d4410c96..00d0fca119e 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -33,8 +33,8 @@ EXPORTS
myodbc_remove_escape
mysql_affected_rows
mysql_autocommit
- mysql_bind_param
- mysql_bind_result
+ mysql_stmt_bind_param
+ mysql_stmt_bind_result
mysql_change_user
mysql_character_set_name
mysql_close
@@ -46,9 +46,9 @@ EXPORTS
mysql_errno
mysql_error
mysql_escape_string
- mysql_execute
- mysql_fetch
- mysql_fetch_column
+ mysql_stmt_execute
+ mysql_stmt_fetch
+ mysql_stmt_fetch_column
mysql_fetch_field
mysql_fetch_field_direct
mysql_fetch_fields
@@ -78,11 +78,11 @@ EXPORTS
mysql_num_rows
mysql_odbc_escape_string
mysql_options
- mysql_param_count
- mysql_param_result
+ mysql_stmt_param_count
+ mysql_stmt_param_metadata
mysql_ping
mysql_prepare
- mysql_get_metadata
+ mysql_stmt_result_metadata
mysql_query
mysql_read_query_result
mysql_real_connect
@@ -93,7 +93,7 @@ EXPORTS
mysql_row_seek
mysql_row_tell
mysql_select_db
- mysql_send_long_data
+ mysql_stmt_send_long_data
mysql_send_query
mysql_shutdown
mysql_ssl_set
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index f44b14b0030..83bd9d5f52b 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -234,7 +234,7 @@ static void emb_free_embedded_thd(MYSQL *mysql)
delete thd;
}
-static const char * emb_read_statistic(MYSQL *mysql)
+static const char * emb_read_statistics(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
return thd->net.last_error;
@@ -246,7 +246,7 @@ static MYSQL_RES * emb_mysql_store_result(MYSQL *mysql)
return mysql_store_result(mysql);
}
-int emb_next_result(MYSQL *mysql)
+my_bool emb_next_result(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
DBUG_ENTER("emb_next_result");
@@ -279,7 +279,7 @@ MYSQL_METHODS embedded_methods=
emb_read_binary_rows,
emb_unbuffered_fetch,
emb_free_embedded_thd,
- emb_read_statistic,
+ emb_read_statistics,
emb_next_result,
emb_read_change_user_result
};
@@ -398,28 +398,11 @@ int init_embedded_server(int argc, char **argv, char **groups)
udf_init();
#endif
- if (opt_bin_log)
- {
- if (!opt_bin_logname)
- {
- char tmp[FN_REFLEN];
- /* TODO: The following should be using fn_format(); We just need to
- first change fn_format() to cut the file name if it's too long.
- */
- strmake(tmp,glob_hostname,FN_REFLEN-5);
- strmov(strcend(tmp,'.'),"-bin");
- opt_bin_logname=my_strdup(tmp,MYF(MY_WME));
- }
- open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
- opt_binlog_index_name, LOG_BIN, 0, 0, max_binlog_size);
- using_update_log=1;
- }
-
(void) thr_setconcurrency(concurrency); // 10 by default
if (
#ifdef HAVE_BERKELEY_DB
- !berkeley_skip ||
+ (have_berkeley_db == SHOW_OPTION_YES) ||
#endif
(flush_time && flush_time != ~(ulong) 0L))
{
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 447744b0521..bff1232750e 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -54,8 +54,9 @@ static double _nwghts[11]=
static double *nwghts=_nwghts+5; /* nwghts[i] = -0.5*1.5**i */
#define FTB_FLAG_TRUNC 1 /* MUST be 1 */
-#define FTB_FLAG_YES 2 /* These two - YES and NO */
-#define FTB_FLAG_NO 4 /* should NEVER be set both */
+#define FTB_FLAG_YES 2 /* no two from these three */
+#define FTB_FLAG_NO 4 /* YES, NO, WONLY */
+#define FTB_FLAG_WONLY 8 /* should be ever set both */
typedef struct st_ftb_expr FTB_EXPR;
struct st_ftb_expr
@@ -504,7 +505,8 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
ftbe->cur_weight += weight;
if ((int) ftbe->yesses < ythresh)
break;
- yn= ((int) ftbe->yesses++ == ythresh) ? ftbe->flags : 0 ;
+ if (!(yn & FTB_FLAG_WONLY))
+ yn= ((int) ftbe->yesses++ == ythresh) ? ftbe->flags : FTB_FLAG_WONLY ;
weight*= ftbe->weight;
}
}
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 4d29838ecd0..cdaed59cd01 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -98,7 +98,9 @@ int chk_status(MI_CHECK *param, register MI_INFO *info)
/* Don't count this as a real warning, as check can correct this ! */
uint save=param->warning_printed;
mi_check_print_warning(param,
- "%d clients is using or hasn't closed the table properly",
+ share->state.open_count==1 ?
+ "%d client is using or hasn't closed the table properly" :
+ "%d clients are using or haven't closed the table properly",
share->state.open_count);
/* If this will be fixed by the check, forget the warning */
if (param->testflag & T_UPDATE_STATE)
@@ -3833,7 +3835,7 @@ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
return 0;
}
err:
- mi_check_print_error(param,"%d when updateing keyfile",my_errno);
+ mi_check_print_error(param,"%d when updating keyfile",my_errno);
return 1;
}
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index ce072d7d57e..4b011ca424f 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -19,6 +19,9 @@
#include <sys/mman.h>
#endif
+static void mi_extra_keyflag(MI_INFO *info, enum ha_extra_function function);
+
+
/*
Set options and buffers to optimize table handling
@@ -355,6 +358,10 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
case HA_EXTRA_PRELOAD_BUFFER_SIZE:
info->preload_buff_size= *((ulong *) extra_arg);
break;
+ case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
+ case HA_EXTRA_CHANGE_KEY_TO_DUP:
+ mi_extra_keyflag(info, function);
+ break;
case HA_EXTRA_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE:
default:
@@ -367,3 +374,27 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
}
DBUG_RETURN(error);
} /* mi_extra */
+
+
+/*
+ Start/Stop Inserting Duplicates Into a Table, WL#1648.
+ */
+static void mi_extra_keyflag(MI_INFO *info, enum ha_extra_function function)
+{
+ uint idx;
+
+ for (idx= 0; idx< info->s->base.keys; idx++)
+ {
+ switch (function) {
+ case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
+ info->s->keyinfo[idx].flag|= HA_NOSAME;
+ break;
+ case HA_EXTRA_CHANGE_KEY_TO_DUP:
+ info->s->keyinfo[idx].flag&= ~(HA_NOSAME);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
diff --git a/myisam/myisam_ftdump.c b/myisam/myisam_ftdump.c
index 015604aa1ad..7d1b20eb854 100644
--- a/myisam/myisam_ftdump.c
+++ b/myisam/myisam_ftdump.c
@@ -267,7 +267,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
static void usage()
{
- printf("Use: ft_dump <table_name> <index_no>\n");
+ printf("Use: myisam_ftdump <table_name> <index_num>\n");
my_print_help(my_long_options);
my_print_variables(my_long_options);
exit(1);
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index a7528a14353..8a87f307a67 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -170,7 +170,7 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
"Directory where character sets are.",
- (gptr*) &set_charset_name, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"check", 'c',
"Check table for errors.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -253,7 +253,7 @@ static struct my_option my_long_options[] =
0, GET_ULL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"set-character-set", OPT_SET_CHARSET,
"Change the character set used by the index",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &set_charset_name, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"set-variable", 'O',
"Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
diff --git a/mysql-test/include/system_db_struct.inc b/mysql-test/include/system_db_struct.inc
new file mode 100644
index 00000000000..5a7aa26c65a
--- /dev/null
+++ b/mysql-test/include/system_db_struct.inc
@@ -0,0 +1,12 @@
+#
+# This test must examine structure of current system database
+#
+
+-- replace_result Tables_in_mysql Tables_in_db Tables_in_test Tables_in_db
+show tables;
+show create table db;
+show create table host;
+show create table user;
+show create table func;
+show create table tables_priv;
+show create table columns_priv;
diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh
index 11ed1bb312c..ac5435f9832 100644
--- a/mysql-test/install_test_db.sh
+++ b/mysql-test/install_test_db.sh
@@ -5,20 +5,27 @@
# This scripts creates the privilege tables db, host, user, tables_priv,
# columns_priv in the mysql database, as well as the func table.
-if [ x$1 = x"-bin" ]; then
- shift 1
- execdir=../bin
- bindir=../bin
- BINARY_DIST=1
- fix_bin=mysql-test
- scriptdir=../bin
- libexecdir=../libexec
+if [ x$1 = x"--bin" ]; then
+ shift 1
+
+ # Check if it's a binary distribution or a 'make install'
+ if test -x ../libexec/mysqld
+ then
+ execdir=../libexec
+ else
+ execdir=../bin
+ fi
+ bindir=../bin
+ BINARY_DIST=1
+ fix_bin=mysql-test
+ scriptdir=../bin
+ libexecdir=../libexec
else
- execdir=../sql
- bindir=../client
- fix_bin=.
- scriptdir=../scripts
- libexecdir=../libexec
+ execdir=../sql
+ bindir=../client
+ fix_bin=.
+ scriptdir=../scripts
+ libexecdir=../libexec
fi
vardir=var
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index a1e5322f35d..b4d5958fb50 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -10,7 +10,7 @@
# Access Definitions
#--
DB=test
-DBPASSWD=
+DBPASSWD=""
VERBOSE=""
USE_MANAGER=0
MY_TZ=GMT-3
@@ -18,7 +18,14 @@ TZ=$MY_TZ; export TZ # for UNIX_TIMESTAMP tests to work
LOCAL_SOCKET=@MYSQL_UNIX_ADDR@
# For query_cache test
-ulimit -n 1024
+case `uname` in
+ SCO_SV | UnixWare | OpenUNIX )
+ # do nothing (Causes strange behavior)
+ ;;
+ * )
+ ulimit -n 1024
+ ;;
+esac
#++
# Program Definitions
@@ -312,6 +319,8 @@ while test $# -gt 0; do
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with --gdb option"
fi
DO_GDB=1
+ EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --gdb"
+ EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --gdb"
# This needs to be checked properly
# USE_MANAGER=1
USE_RUNNING_SERVER=""
@@ -413,8 +422,7 @@ SLAVE_MYERR="$MYSQL_TEST_DIR/var/log/slave.err"
CURRENT_TEST="$MYSQL_TEST_DIR/var/log/current_test"
SMALL_SERVER="--key_buffer_size=1M --sort_buffer=256K --max_heap_table_size=1M"
-export MASTER_MYPORT
-export SLAVE_MYPORT
+export MASTER_MYPORT SLAVE_MYPORT
if [ x$SOURCE_DIST = x1 ] ; then
MY_BASEDIR=$MYSQL_TEST_DIR
@@ -461,15 +469,17 @@ if [ x$SOURCE_DIST = x1 ] ; then
MYSQL_TEST="strace -o $MYSQL_TEST_DIR/var/log/mysqltest.strace $MYSQL_TEST"
fi
- MYSQLADMIN="$BASEDIR/client/mysqladmin"
+ CLIENT_BINDIR="$BASEDIR/client"
+ MYSQLADMIN="$CLIENT_BINDIR/mysqladmin"
WAIT_PID="$BASEDIR/extra/mysql_waitpid"
- MYSQL_MANAGER_CLIENT="$BASEDIR/client/mysqlmanagerc"
+ MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqlmanagerc"
MYSQL_MANAGER="$BASEDIR/tools/mysqlmanager"
- MYSQL_MANAGER_PWGEN="$BASEDIR/client/mysqlmanager-pwgen"
- MYSQL="$BASEDIR/client/mysql"
+ MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqlmanager-pwgen"
+ MYSQL="$CLIENT_BINDIR/mysql"
LANGUAGE="$BASEDIR/sql/share/english/"
CHARSETSDIR="$BASEDIR/sql/share/charsets"
INSTALL_DB="./install_test_db"
+ MYSQL_FIX_SYSTEM_TABLES="$BASEDIR/scripts/mysql_fix_privilege_tables"
else
if test -x "$BASEDIR/libexec/mysqld"
then
@@ -477,16 +487,18 @@ else
else
MYSQLD="$VALGRIND $BASEDIR/bin/mysqld"
fi
- MYSQL_TEST="$BASEDIR/bin/mysqltest"
- MYSQL_DUMP="$BASEDIR/bin/mysqldump"
- MYSQL_BINLOG="$BASEDIR/bin/mysqlbinlog"
- MYSQLADMIN="$BASEDIR/bin/mysqladmin"
- WAIT_PID="$BASEDIR/bin/mysql_waitpid"
- MYSQL_MANAGER="$BASEDIR/bin/mysqlmanager"
- MYSQL_MANAGER_CLIENT="$BASEDIR/bin/mysqlmanagerc"
- MYSQL_MANAGER_PWGEN="$BASEDIR/bin/mysqlmanager-pwgen"
- MYSQL="$BASEDIR/bin/mysql"
- INSTALL_DB="./install_test_db -bin"
+ CLIENT_BINDIR="$BASEDIR/bin"
+ MYSQL_TEST="$CLIENT_BINDIR/mysqltest"
+ MYSQL_DUMP="$CLIENT_BINDIR/mysqldump"
+ MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog"
+ MYSQLADMIN="$CLIENT_BINDIR/mysqladmin"
+ WAIT_PID="$CLIENT_BINDIR/mysql_waitpid"
+ MYSQL_MANAGER="$CLIENT_BINDIR/mysqlmanager"
+ MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqlmanagerc"
+ MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqlmanager-pwgen"
+ MYSQL="$CLIENT_BINDIR/mysql"
+ INSTALL_DB="./install_test_db --bin"
+ MYSQL_FIX_SYSTEM_TABLES="$CLIENT_BINDIR/mysql_fix_privilege_tables"
if test -d "$BASEDIR/share/mysql/english"
then
LANGUAGE="$BASEDIR/share/mysql/english/"
@@ -497,10 +509,12 @@ else
fi
fi
-MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK $EXTRA_MYSQLDUMP_OPT"
+MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR $EXTRA_MYSQLBINLOG_OPT"
-export MYSQL_DUMP
-export MYSQL_BINLOG
+MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose=1"
+MYSQL="$MYSQL --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD"
+export MYSQL MYSQL_DUMP MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES CLIENT_BINDIR
+
if [ -z "$MASTER_MYSQLD" ]
then
@@ -528,9 +542,9 @@ fi
if [ -w / ]
then
- # We are running as root; We need to add the --root argument
- EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --user=root"
- EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --user=root"
+ # We are running as root; We need to add the --root argument
+ EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --user=root"
+ EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --user=root"
fi
@@ -1177,6 +1191,7 @@ run_testcase ()
master_init_script=$TESTDIR/$tname-master.sh
slave_init_script=$TESTDIR/$tname-slave.sh
slave_master_info_file=$TESTDIR/$tname.slave-mi
+ result_file=$tname
echo $tname > $CURRENT_TEST
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
if [ "$USE_MANAGER" = 1 ] ; then
@@ -1226,6 +1241,11 @@ run_testcase ()
# Note that this must be set to space, not "" for test-reset to work
EXTRA_MASTER_OPT=" "
;;
+ --result-file=*)
+ result_file=`$ECHO "$EXTRA_MASTER_OPT" | $SED -e "s;--result-file=;;"`
+ # Note that this must be set to space, not "" for test-reset to work
+ EXTRA_MASTER_OPT=" "
+ ;;
esac
stop_master
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
@@ -1283,7 +1303,7 @@ run_testcase ()
if [ -f $tf ] ; then
$RM -f r/$tname.*reject
- mysql_test_args="-R r/$tname.result $EXTRA_MYSQL_TEST_OPT"
+ mysql_test_args="-R r/$result_file.result $EXTRA_MYSQL_TEST_OPT"
if [ -z "$DO_CLIENT_GDB" ] ; then
`$MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE`;
else
@@ -1318,7 +1338,7 @@ run_testcase ()
$ECHO "$RES$RES_SPACE [ fail ]"
$ECHO
error_is
- show_failed_diff $tname
+ show_failed_diff $result_file
$ECHO
if [ x$FORCE != x1 ] ; then
$ECHO "Aborting: $tname failed. To continue, re-run with '--force'."
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index 703cc59d9a4..dee7433404f 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -343,6 +343,22 @@ t1 CREATE TABLE `t1` (
`a` char(10) character set latin1 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251
drop table t1;
+create table t1 (myblob longblob,mytext longtext)
+default charset latin1 collate latin1_general_cs;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `myblob` longblob,
+ `mytext` longtext character set latin1 collate latin1_general_cs
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 character set latin2;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `myblob` longblob,
+ `mytext` longtext character set latin2
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
CREATE TABLE t1 (
Host varchar(16) binary NOT NULL default '',
User varchar(16) binary NOT NULL default '',
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index e6a010a7542..343ab89e6b5 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -104,9 +104,9 @@ drop table t2;
create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME) as t, CAST("2001-12-29 20:45:11" AS DATETIME) as dt;
describe t2;
Field Type Null Key Default Extra
-d date 0000-00-00
-t time 00:00:00
-dt datetime 0000-00-00 00:00:00
+d date YES NULL
+t time YES NULL
+dt datetime YES NULL
drop table t1,t2;
create table t1 (a tinyint);
create table t2 (a int) select * from t1;
@@ -262,6 +262,12 @@ a b
0 2
3 4
drop table t1;
+create table `t1 `(a int);
+ERROR 42000: Incorrect table name 't1 '
+create database `db1 `;
+ERROR 42000: Incorrect database name 'db1 '
+create table t1(`a ` int);
+ERROR 42000: Incorrect column name 'a '
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;
@@ -396,12 +402,12 @@ Field Type Null Key Default Extra
a int(11) YES NULL
b bigint(11) 0
c bigint(10) 0
-d date 0000-00-00
+d date YES NULL
e char(1)
-f datetime 0000-00-00 00:00:00
-g time 00:00:00
+f datetime YES NULL
+g time YES NULL
h longblob
-dd time 00:00:00
+dd time YES NULL
select * from t2;
a b c d e f g h dd
1 -7 7 2000-01-01 b 2000-01-01 00:00:00 05:04:03 yet another binary data 02:00:00
@@ -456,6 +462,20 @@ Field Type Null Key Default Extra
name varchar(10) YES NULL
age smallint(6) YES -1
drop table t1, t2;
+create table t1(cenum enum('a'), cset set('b'));
+create table t2(cenum enum('a','a'), cset set('b','b'));
+Warnings:
+Note 1291 Column 'cenum' has duplicated value 'a' in ENUM
+Note 1291 Column 'cset' has duplicated value 'b' in SET
+create table t3(cenum enum('a','A','a','c','c'), cset set('b','B','b','d','d'));
+Warnings:
+Note 1291 Column 'cenum' has duplicated value 'a' in ENUM
+Note 1291 Column 'cenum' has duplicated value 'A' in ENUM
+Note 1291 Column 'cenum' has duplicated value 'c' in ENUM
+Note 1291 Column 'cset' has duplicated value 'b' in SET
+Note 1291 Column 'cset' has duplicated value 'B' in SET
+Note 1291 Column 'cset' has duplicated value 'd' in SET
+drop table t1, t2, t3;
create database test_$1;
use test_$1;
select database();
@@ -468,3 +488,44 @@ NULL
select database();
database()
NULL
+use test;
+create table t1 (a int, index `primary` (a));
+ERROR 42000: Incorrect index name 'primary'
+create table t1 (a int, index `PRIMARY` (a));
+ERROR 42000: Incorrect index name 'PRIMARY'
+create table t1 (`primary` int, index(`primary`));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `primary` int(11) default NULL,
+ KEY `primary_2` (`primary`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t2 (`PRIMARY` int, index(`PRIMARY`));
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `PRIMARY` int(11) default NULL,
+ KEY `PRIMARY_2` (`PRIMARY`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t3 (a int);
+alter table t3 add index `primary` (a);
+ERROR 42000: Incorrect index name 'primary'
+alter table t3 add index `PRIMARY` (a);
+ERROR 42000: Incorrect index name 'PRIMARY'
+create table t4 (`primary` int);
+alter table t4 add index(`primary`);
+show create table t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `primary` int(11) default NULL,
+ KEY `primary_2` (`primary`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t5 (`PRIMARY` int);
+alter table t5 add index(`PRIMARY`);
+show create table t5;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `PRIMARY` int(11) default NULL,
+ KEY `PRIMARY_2` (`PRIMARY`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1, t2, t3, t4, t5;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index ddb5355f9ec..aacd80f19bb 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -169,3 +169,28 @@ hex(s1)
drop table t1;
create table t1 (a text character set utf8, primary key(a(360)));
ERROR 42000: Specified key was too long; max key length is 1000 bytes
+CREATE TABLE t1 ( a varchar(10) ) CHARACTER SET utf8;
+INSERT INTO t1 VALUES ( 'test' );
+SELECT a.a, b.a FROM t1 a, t1 b WHERE a.a = b.a;
+a a
+test test
+SELECT a.a, b.a FROM t1 a, t1 b WHERE a.a = 'test' and b.a = 'test';
+a a
+test test
+SELECT a.a, b.a FROM t1 a, t1 b WHERE a.a = b.a and a.a = 'test';
+a a
+test test
+DROP TABLE t1;
+create table t1 (a char(255) character set utf8);
+insert into t1 values('b'),('b');
+select * from t1 where a = 'b';
+a
+b
+b
+select * from t1 where a = 'b' and a = 'b';
+a
+b
+b
+select * from t1 where a = 'b' and a != 'b';
+a
+drop table t1;
diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result
index 165a8d7011c..f1582707cf5 100644
--- a/mysql-test/r/date_formats.result
+++ b/mysql-test/r/date_formats.result
@@ -78,11 +78,11 @@ select str_to_date(concat('15-01-2001',' 2:59:58.999'),
concat('%d-%m-%Y',' ','%H:%i:%s.%f'));
str_to_date(concat('15-01-2001',' 2:59:58.999'),
concat('%d-%m-%Y',' ','%H:%i:%s.%f'))
-2001-01-15 02:59:58.000999
+2001-01-15 02:59:58.999000
create table t1 (date char(30), format char(30) not null);
insert into t1 values
('2003-01-02 10:11:12', '%Y-%m-%d %H:%i:%S'),
-('03-01-02 8:11:2.123456', '%y-%m-%d %H:%i:%S'),
+('03-01-02 8:11:2.123456', '%y-%m-%d %H:%i:%S.%#'),
('2003-01-02 10:11:12 PM', '%Y-%m-%d %h:%i:%S %p'),
('2003-01-02 01:11:12.12345AM', '%Y-%m-%d %h:%i:%S.%f%p'),
('2003-01-02 02:11:12.12345AM', '%Y-%m-%d %h:%i:%S.%f %p'),
@@ -106,16 +106,16 @@ insert into t1 values
select date,format,str_to_date(date, format) as str_to_date from t1;
date format str_to_date
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 2003-01-02 10:11:12
-03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 2003-01-02 08:11:02
+03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 2003-01-02 08:11:02
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02 22:11:12
-2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.012345
-2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.012345
-2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.012345
+2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.123450
+2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.123450
+2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.123450
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12
10:20:10 %H:%i:%s 0000-00-00 10:20:10
10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10
10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10
-10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.000044
+10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58
15 September 2001 %d %M %Y 2001-09-15 00:00:00
15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00
@@ -130,16 +130,16 @@ Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00
select date,format,concat('',str_to_date(date, format)) as con from t1;
date format con
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 2003-01-02 10:11:12
-03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 2003-01-02 08:11:02
+03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 2003-01-02 08:11:02
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02 22:11:12
-2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.012345
-2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.012345
-2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.012345
+2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.123450
+2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.123450
+2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.123450
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12
10:20:10 %H:%i:%s 0000-00-00 10:20:10
10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10
10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10
-10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.000044
+10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58
15 September 2001 %d %M %Y 2001-09-15 00:00:00
15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00
@@ -154,16 +154,16 @@ Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00
select date,format,cast(str_to_date(date, format) as datetime) as datetime from t1;
date format datetime
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 2003-01-02 10:11:12
-03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 2003-01-02 08:11:02
+03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 2003-01-02 08:11:02
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02 22:11:12
-2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.012345
-2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.012345
-2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.012345
+2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.123450
+2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.123450
+2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.123450
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12
10:20:10 %H:%i:%s 0000-00-00 10:20:10
10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10
10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10
-10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.000044
+10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58
15 September 2001 %d %M %Y 2001-09-15 00:00:00
15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00
@@ -178,7 +178,7 @@ Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00
select date,format,DATE(str_to_date(date, format)) as date2 from t1;
date format date2
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 2003-01-02
-03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 2003-01-02
+03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 2003-01-02
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02
@@ -202,16 +202,16 @@ Thursday 53 1998 %W %u %Y 1998-12-31
select date,format,TIME(str_to_date(date, format)) as time from t1;
date format time
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 10:11:12
-03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 08:11:02
+03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 08:11:02
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 22:11:12
-2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 01:11:12.012345
-2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.012345
-2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.012345
+2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 01:11:12.123450
+2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.123450
+2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.123450
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12
10:20:10 %H:%i:%s 10:20:10
10:20:10 %h:%i:%s.%f 10:20:10
10:20:10AM %h:%i:%s%p 10:20:10
-10:20:10.44AM %h:%i:%s.%f%p 10:20:10.000044
+10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58
15 September 2001 %d %M %Y 00:00:00
15 SEPTEMB 2001 %d %M %Y 00:00:00
@@ -226,16 +226,16 @@ Thursday 53 1998 %W %u %Y 00:00:00
select date,format,concat(TIME(str_to_date(date, format))) as time2 from t1;
date format time2
2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 10:11:12
-03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S 08:11:02
+03-01-02 8:11:2.123456 %y-%m-%d %H:%i:%S.%# 08:11:02
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 22:11:12
-2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 01:11:12.012345
-2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.012345
-2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.012345
+2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 01:11:12.123450
+2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.123450
+2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.123450
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12
10:20:10 %H:%i:%s 10:20:10
10:20:10 %h:%i:%s.%f 10:20:10
10:20:10AM %h:%i:%s%p 10:20:10
-10:20:10.44AM %h:%i:%s.%f%p 10:20:10.000044
+10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58
15 September 2001 %d %M %Y 00:00:00
15 SEPTEMB 2001 %d %M %Y 00:00:00
@@ -302,11 +302,15 @@ date format str_to_date
10:20:10AM %h:%i:%s 0000-00-00 10:20:10
2003-01-02 10:11:12 %Y-%m-%d %h:%i:%S 2003-01-02 10:11:12
03-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 0003-01-02 22:11:12
+Warnings:
+Note 1292 Truncated wrong string value: '10:20:10AM'
select date,format,concat(str_to_date(date, format),'') as con from t1;
date format con
10:20:10AM %h:%i:%s 0000-00-00 10:20:10
2003-01-02 10:11:12 %Y-%m-%d %h:%i:%S 2003-01-02 10:11:12
03-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 0003-01-02 22:11:12
+Warnings:
+Note 1292 Truncated wrong string value: '10:20:10AM'
drop table t1;
select get_format(DATE, 'USA') as a;
a
@@ -335,3 +339,56 @@ date_format(d,"%d")
14
14
drop table t1;
+select str_to_date("2003-....01ABCD-02 10:11:12.0012", "%Y-%.%m%@-%d %H:%i:%S.%f") as a;
+a
+2003-01-02 10:11:12.001200
+create table t1 select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
+str_to_date("10:11:12.0012", "%H:%i:%S.%f") as f2,
+str_to_date("2003-01-02", "%Y-%m-%d") as f3,
+str_to_date("02", "%d") as f4, str_to_date("02 10", "%d %H") as f5;
+describe t1;
+Field Type Null Key Default Extra
+f1 datetime YES NULL
+f2 time YES NULL
+f3 date YES NULL
+f4 date YES NULL
+f5 time YES NULL
+select * from t1;
+f1 f2 f3 f4 f5
+2003-01-02 10:11:12 10:11:12 2003-01-02 0000-00-02 58:00:00
+drop table t1;
+create table t1 select "02 10" as a, "%d %H" as b;
+select str_to_date(a,b) from t1;
+str_to_date(a,b)
+0000-00-02 10:00:00
+create table t2 select str_to_date(a,b) from t1;
+describe t2;
+Field Type Null Key Default Extra
+str_to_date(a,b) char(29) YES NULL
+select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
+str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S") as f2,
+str_to_date("2003-01-02", "%Y-%m-%d") as f3,
+str_to_date("02 10:11:12", "%d %H:%i:%S.%f") as f4,
+str_to_date("02 10:11:12", "%d %H:%i:%S") as f5,
+str_to_date("02 10", "%d %f") as f6;
+f1 f2 f3 f4 f5 f6
+2003-01-02 10:11:12.001200 2003-01-02 10:11:12 2003-01-02 58:11:12 58:11:12 48:00:00.100000
+Warnings:
+Note 1292 Truncated wrong datetime value: '2003-01-02 10:11:12.0012'
+drop table t1, t2;
+select str_to_date("2003-01-02 10:11:12.0012ABCD", "%Y-%m-%d %H:%i:%S.%f") as f1,
+addtime("-01:01:01.01 GGG", "-23:59:59.1") as f2,
+microsecond("1997-12-31 23:59:59.01XXXX") as f3;
+f1 f2 f3
+2003-01-02 10:11:12.001200 -25:01:00.110000 10000
+Warnings:
+Note 1292 Truncated wrong datetime value: '2003-01-02 10:11:12.0012ABCD'
+Note 1292 Truncated wrong time value: '-01:01:01.01 GG'
+Note 1292 Truncated wrong datetime value: '1997-12-31 23:59:59.01XXXX'
+select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1,
+str_to_date("2003-04-05 10:11:12.101010234567", "%Y-%m-%d %H:%i:%S.%f") as f2;
+f1 f2
+2003-04-05 2003-04-05 10:11:12.101010
+Warnings:
+Note 1292 Truncated wrong date value: '2003-04-05 g'
+Note 1292 Truncated wrong datetime value: '2003-04-05 10:11:12.101010234567'
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index be743be386b..f5754bb3332 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -271,8 +271,8 @@ delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Cou
select * from t1;
N M
3 0
-delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
-ERROR HY000: The target table P2 of the DELETE is not updatable
+delete P1.*,p2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS p2 ON P1.N = p2.N;
+ERROR HY000: The target table p2 of the DELETE is not updatable
delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
ERROR 42S22: Unknown column 'aaa' in 'field list'
drop table t1;
@@ -320,3 +320,9 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t2 range PRIMARY PRIMARY 4 NULL 2 Using where; Using index
drop table t2;
+CREATE TABLE `t1` ( `itemid` int(11) NOT NULL default '0', `grpid` varchar(15) NOT NULL default '', `vendor` int(11) NOT NULL default '0', `date_` date NOT NULL default '0000-00-00', `price` decimal(12,2) NOT NULL default '0.00', PRIMARY KEY (`itemid`,`grpid`,`vendor`,`date_`), KEY `itemid` (`itemid`,`vendor`), KEY `itemid_2` (`itemid`,`date_`));
+insert into t1 values (128, 'rozn', 2, now(), 10),(128, 'rozn', 1, now(), 10);
+SELECT MIN(price) min, MAX(price) max, AVG(price) avg FROM (SELECT SUBSTRING( MAX(concat(date_,";",price)), 12) price FROM t1 WHERE itemid=128 AND grpid='rozn' GROUP BY itemid, grpid, vendor) lastprices;
+min max avg
+10.00 10.00 10
+DROP TABLE t1;
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index 3748af1b8f9..8b919964163 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -21,6 +21,7 @@ select * from mysqltest.mysqltest;
n
4
drop database if exists mysqltest;
+affected rows: 1
create database mysqltest;
drop database mysqltest;
flush tables with read lock;
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index 0c9fcb9a55e..02850e4d902 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -142,6 +142,10 @@ a b
MySQL has now support for full-text search
select * from t1 where MATCH a,b AGAINST ('"text i"' IN BOOLEAN MODE);
a b
+select * from t1 where MATCH a,b AGAINST ('+(support collections) +foobar*' IN BOOLEAN MODE);
+a b
+select * from t1 where MATCH a,b AGAINST ('+(+(support collections)) +foobar*' IN BOOLEAN MODE);
+a b
select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE);
a b
select * from t1 where MATCH a,b AGAINST('"space model' IN BOOLEAN MODE);
diff --git a/mysql-test/r/fulltext_var.result b/mysql-test/r/fulltext_var.result
index cdbbfc3f5ea..50afea2a500 100644
--- a/mysql-test/r/fulltext_var.result
+++ b/mysql-test/r/fulltext_var.result
@@ -2,8 +2,8 @@ drop table if exists t1;
show variables like "ft\_%";
Variable_name Value
ft_boolean_syntax + -><()~*:""&|
-ft_min_word_len 4
ft_max_word_len 84
+ft_min_word_len 4
ft_query_expansion_limit 20
ft_stopword_file (built-in)
create table t1 (b text not null);
diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result
index bea16c07f86..0a04585d77d 100644
--- a/mysql-test/r/func_if.result
+++ b/mysql-test/r/func_if.result
@@ -59,6 +59,12 @@ id select_type table type possible_keys key key_len ref rows Extra
Warnings:
Note 1003 select high_priority nullif((test.t1.u = 0),_latin1'test') AS `nullif(u=0, 'test')` from test.t1
drop table t1;
+select NULLIF(NULL,NULL), NULLIF(NULL,1), NULLIF(NULL,1.0), NULLIF(NULL,"test");
+NULLIF(NULL,NULL) NULLIF(NULL,1) NULLIF(NULL,1.0) NULLIF(NULL,"test")
+NULL NULL NULL NULL
+select NULLIF(1,NULL), NULLIF(1.0, NULL), NULLIF("test", NULL);
+NULLIF(1,NULL) NULLIF(1.0, NULL) NULLIF("test", NULL)
+1 1.0 test
create table t1 (num double(12,2));
insert into t1 values (144.54);
select sum(if(num is null,0.00,num)) from t1;
diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result
index 7f722622be1..75692738caf 100644
--- a/mysql-test/r/func_like.result
+++ b/mysql-test/r/func_like.result
@@ -46,6 +46,12 @@ select * from t1 where a like 'a\\%' escape '#' and a like 'a\\\\b';
a
a\b
drop table t1;
+create table t1 (a datetime);
+insert into t1 values ('2004-03-11 12:00:21');
+select * from t1 where a like '2004-03-11 12:00:21';
+a
+2004-03-11 12:00:21
+drop table t1;
SET NAMES koi8r;
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET koi8r);
INSERT INTO t1 VALUES ('ÆÙ×Á'),('æÙ×Á'),('Æù×Á'),('ÆÙ÷Á'),('ÆÙ×á'),('æù÷á');
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index 9400c3b9d6b..5a9f0f68228 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -19,6 +19,9 @@ hex(inet_aton('127.1'))
select hex(inet_aton('127.1.1'));
hex(inet_aton('127.1.1'))
7F010001
+select length(uuid()), charset(uuid()), length(unhex(replace(uuid(),_utf8'-',_utf8'')));
+length(uuid()) charset(uuid()) length(unhex(replace(uuid(),_utf8'-',_utf8'')))
+36 utf8 16
select length(format('nan', 2)) > 0;
length(format('nan', 2)) > 0
1
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index e330c73727b..31868261157 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -159,14 +159,14 @@ time("1997-12-31 23:59:59.000001") as f9;
describe t1;
Field Type Null Key Default Extra
f1 date 0000-00-00
-f2 datetime 0000-00-00 00:00:00
-f3 time 00:00:00
+f2 datetime YES NULL
+f3 time YES NULL
f4 time 00:00:00
f5 time 00:00:00
f6 time 00:00:00
-f7 datetime 0000-00-00 00:00:00
-f8 date 0000-00-00
-f9 time 00:00:00
+f7 datetime YES NULL
+f8 date YES NULL
+f9 time YES NULL
select * from t1;
f1 f2 f3 f4 f5 f6 f7 f8 f9
1997-01-01 1998-01-02 01:01:00 49:01:01 46:58:57 -23:59:59 10:11:12 2001-12-01 01:01:01 1997-12-31 23:59:59
@@ -198,3 +198,18 @@ NULL NULL
NULL NULL
00:00:00 -24:00:00
drop table t1, test;
+select addtime("-01:01:01.01", "-23:59:59.1") as a;
+a
+-25:01:00.110000
+select microsecond("1997-12-31 23:59:59.01") as a;
+a
+10000
+select microsecond(19971231235959.01) as a;
+a
+10000
+select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a;
+a
+1997-12-31 00:00:10.090000
+select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f");
+str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f")
+2003-01-02 10:11:12.001200
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index c9eba2f2505..d3225679b3e 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -192,6 +192,15 @@ length(quote(concat(char(0),"test")))
select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235))));
hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235))))
27E0E3E6E7E8EAEB27
+select unhex(hex("foobar")), hex(unhex("1234567890ABCDEF")), unhex("345678");
+unhex(hex("foobar")) hex(unhex("1234567890ABCDEF")) unhex("345678")
+foobar 1234567890ABCDEF 4Vx
+select hex(unhex("1")), hex(unhex("12")), hex(unhex("123")), hex(unhex("1234")), hex(unhex("12345")), hex(unhex("123456"));
+hex(unhex("1")) hex(unhex("12")) hex(unhex("123")) hex(unhex("1234")) hex(unhex("12345")) hex(unhex("123456"))
+01 12 0123 1234 012345 123456
+select length(unhex(md5("abrakadabra")));
+length(unhex(md5("abrakadabra")))
+16
select reverse("");
reverse("")
@@ -330,6 +339,8 @@ select concat(_latin1'a',_latin2'a',_latin5'a');
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin5_turkish_ci,COERCIBLE) for operation 'concat'
select concat(_latin1'a',_latin2'a',_latin5'a',_latin7'a');
ERROR HY000: Illegal mix of collations for operation 'concat'
+select concat_ws(_latin1'a',_latin2'a');
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat_ws'
select FIELD('b','A','B');
FIELD('b','A','B')
2
@@ -615,3 +626,16 @@ Note 1003 select high_priority md5(_latin1'hello') AS `md5('hello')`,sha(_latin1
SELECT lpad(12345, 5, "#");
lpad(12345, 5, "#")
12345
+SELECT conv(71, 10, 36), conv('1Z', 36, 10);
+conv(71, 10, 36) conv('1Z', 36, 10)
+1Z 71
+create table t1 (id int(1), str varchar(10)) DEFAULT CHARSET=utf8;
+insert into t1 values (1,'aaaaaaaaaa'), (2,'bbbbbbbbbb');
+create table t2 (id int(1), str varchar(10)) DEFAULT CHARSET=utf8;
+insert into t2 values (1,'cccccccccc'), (2,'dddddddddd');
+select substring(concat(t1.str, t2.str), 1, 15) "name" from t1, t2
+where t2.id=t1.id order by name;
+name
+aaaaaaaaaaccccc
+bbbbbbbbbbddddd
+drop table t1, t2;
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 0998f7b8bcf..060a5d0f1bd 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -506,17 +506,32 @@ last_day('2001-01-01 01:01:01') as f5, last_day(NULL),
last_day('2001-02-12');
f1 f2 f3 f4 f5 last_day(NULL) last_day('2001-02-12')
2000-02-29 2002-12-31 NULL 2003-04-30 2001-01-31 NULL 2001-02-28
-create table t1 select last_day('2000-02-05') as a;
+create table t1 select last_day('2000-02-05') as a,
+from_days(to_days("960101")) as b;
describe t1;
Field Type Null Key Default Extra
a date 0000-00-00
+b date YES NULL
select * from t1;
-a
-2000-02-29
+a b
+2000-02-29 1996-01-01
drop table t1;
-select last_day('2000-02-05');
-last_day('2000-02-05')
-2000-02-29
+select last_day('2000-02-05') as a,
+from_days(to_days("960101")) as b;
+a b
+2000-02-29 1996-01-01
+select date_add(last_day("1997-12-1"), INTERVAL 1 DAY);
+date_add(last_day("1997-12-1"), INTERVAL 1 DAY)
+1998-01-01
+select length(last_day("1997-12-1"));
+length(last_day("1997-12-1"))
+10
+select last_day("1997-12-1")+0;
+last_day("1997-12-1")+0
+19971231
+select last_day("1997-12-1")+0.0;
+last_day("1997-12-1")+0.0
+19971231.0
select strcmp(date_sub(localtimestamp(), interval 3 hour), utc_timestamp())=0;
strcmp(date_sub(localtimestamp(), interval 3 hour), utc_timestamp())=0
1
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 7ee16d54724..be33c05c578 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -1,115 +1,115 @@
-DROP TABLE IF EXISTS pt, ls, p, mpt, mls, mp, gc, geo;
-CREATE TABLE pt (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
-CREATE TABLE ls (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
-CREATE TABLE p (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
-CREATE TABLE mpt (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
-CREATE TABLE mls (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
-CREATE TABLE mp (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
-CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
-CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
-SHOW FIELDS FROM pt;
+DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
+CREATE TABLE gis_point (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
+CREATE TABLE gis_line (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
+CREATE TABLE gis_polygon (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
+CREATE TABLE gis_multi_point (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
+CREATE TABLE gis_multi_line (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
+CREATE TABLE gis_multi_polygon (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
+CREATE TABLE gis_geometrycollection (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
+CREATE TABLE gis_geometry (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
+SHOW FIELDS FROM gis_point;
Field Type Null Key Default Extra
fid int(11) PRI 0
g point YES NULL
-SHOW FIELDS FROM ls;
+SHOW FIELDS FROM gis_line;
Field Type Null Key Default Extra
fid int(11) PRI 0
g linestring YES NULL
-SHOW FIELDS FROM p;
+SHOW FIELDS FROM gis_polygon;
Field Type Null Key Default Extra
fid int(11) PRI 0
g polygon YES NULL
-SHOW FIELDS FROM mpt;
+SHOW FIELDS FROM gis_multi_point;
Field Type Null Key Default Extra
fid int(11) PRI 0
g multipoint YES NULL
-SHOW FIELDS FROM mls;
+SHOW FIELDS FROM gis_multi_line;
Field Type Null Key Default Extra
fid int(11) PRI 0
g multilinestring YES NULL
-SHOW FIELDS FROM mp;
+SHOW FIELDS FROM gis_multi_polygon;
Field Type Null Key Default Extra
fid int(11) PRI 0
g multipolygon YES NULL
-SHOW FIELDS FROM gc;
+SHOW FIELDS FROM gis_geometrycollection;
Field Type Null Key Default Extra
fid int(11) PRI 0
g geometrycollection YES NULL
-SHOW FIELDS FROM geo;
+SHOW FIELDS FROM gis_geometry;
Field Type Null Key Default Extra
fid int(11) PRI 0
g geometry YES NULL
-INSERT INTO pt VALUES
+INSERT INTO gis_point VALUES
(101, PointFromText('POINT(10 10)')),
(102, PointFromText('POINT(20 10)')),
(103, PointFromText('POINT(20 20)')),
(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)'))));
-INSERT INTO ls VALUES
+INSERT INTO gis_line VALUES
(105, LineFromText('LINESTRING(0 0,0 10,10 0)')),
(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')),
(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10))));
-INSERT INTO p VALUES
+INSERT INTO gis_polygon VALUES
(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')),
(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')),
(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)))));
-INSERT INTO mpt VALUES
+INSERT INTO gis_multi_point VALUES
(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')),
(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')),
(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10))));
-INSERT INTO mls VALUES
+INSERT INTO gis_multi_line VALUES
(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')),
(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')),
(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7)))));
-INSERT INTO mp VALUES
+INSERT INTO gis_multi_polygon VALUES
(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3))))));
-INSERT INTO gc VALUES
+INSERT INTO gis_geometrycollection VALUES
(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')),
(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))));
-INSERT into geo SELECT * FROM pt;
-INSERT into geo SELECT * FROM ls;
-INSERT into geo SELECT * FROM p;
-INSERT into geo SELECT * FROM mpt;
-INSERT into geo SELECT * FROM mls;
-INSERT into geo SELECT * FROM mp;
-INSERT into geo SELECT * FROM gc;
-SELECT fid, AsText(g) FROM pt;
+INSERT into gis_geometry SELECT * FROM gis_point;
+INSERT into gis_geometry SELECT * FROM gis_line;
+INSERT into gis_geometry SELECT * FROM gis_polygon;
+INSERT into gis_geometry SELECT * FROM gis_multi_point;
+INSERT into gis_geometry SELECT * FROM gis_multi_line;
+INSERT into gis_geometry SELECT * FROM gis_multi_polygon;
+INSERT into gis_geometry SELECT * FROM gis_geometrycollection;
+SELECT fid, AsText(g) FROM gis_point;
fid AsText(g)
101 POINT(10 10)
102 POINT(20 10)
103 POINT(20 20)
104 POINT(10 20)
-SELECT fid, AsText(g) FROM ls;
+SELECT fid, AsText(g) FROM gis_line;
fid AsText(g)
105 LINESTRING(0 0,0 10,10 0)
106 LINESTRING(10 10,20 10,20 20,10 20,10 10)
107 LINESTRING(10 10,40 10)
-SELECT fid, AsText(g) FROM p;
+SELECT fid, AsText(g) FROM gis_polygon;
fid AsText(g)
108 POLYGON((10 10,20 10,20 20,10 20,10 10))
109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10))
110 POLYGON((0 0,30 0,30 30,0 0))
-SELECT fid, AsText(g) FROM mpt;
+SELECT fid, AsText(g) FROM gis_multi_point;
fid AsText(g)
111 MULTIPOINT(0 0,10 10,10 20,20 20)
112 MULTIPOINT(1 1,11 11,11 21,21 21)
113 MULTIPOINT(3 6,4 10)
-SELECT fid, AsText(g) FROM mls;
+SELECT fid, AsText(g) FROM gis_multi_line;
fid AsText(g)
114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))
115 MULTILINESTRING((10 48,10 21,10 0))
116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7))
-SELECT fid, AsText(g) FROM mp;
+SELECT fid, AsText(g) FROM gis_multi_polygon;
fid AsText(g)
117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
119 MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
-SELECT fid, AsText(g) FROM gc;
+SELECT fid, AsText(g) FROM gis_geometrycollection;
fid AsText(g)
120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
-SELECT fid, AsText(g) FROM geo;
+SELECT fid, AsText(g) FROM gis_geometry;
fid AsText(g)
101 POINT(10 10)
102 POINT(20 10)
@@ -132,7 +132,7 @@ fid AsText(g)
119 MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
-SELECT fid, Dimension(g) FROM geo;
+SELECT fid, Dimension(g) FROM gis_geometry;
fid Dimension(g)
101 0
102 0
@@ -155,7 +155,7 @@ fid Dimension(g)
119 2
120 1
121 1
-SELECT fid, GeometryType(g) FROM geo;
+SELECT fid, GeometryType(g) FROM gis_geometry;
fid GeometryType(g)
101 POINT
102 POINT
@@ -178,7 +178,7 @@ fid GeometryType(g)
119 MULTIPOLYGON
120 GEOMETRYCOLLECTION
121 GEOMETRYCOLLECTION
-SELECT fid, IsEmpty(g) FROM geo;
+SELECT fid, IsEmpty(g) FROM gis_geometry;
fid IsEmpty(g)
101 0
102 0
@@ -201,7 +201,7 @@ fid IsEmpty(g)
119 0
120 0
121 0
-SELECT fid, AsText(Envelope(g)) FROM geo;
+SELECT fid, AsText(Envelope(g)) FROM gis_geometry;
fid AsText(Envelope(g))
101 POLYGON((10 10,10 10,10 10,10 10,10 10))
102 POLYGON((20 10,20 10,20 10,20 10,20 10))
@@ -224,161 +224,165 @@ fid AsText(Envelope(g))
119 POLYGON((0 0,3 0,3 3,0 3,0 0))
120 POLYGON((0 0,10 0,10 10,0 10,0 0))
121 POLYGON((3 6,44 6,44 9,3 9,3 6))
-explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from geo;
+explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE geo ALL NULL NULL NULL NULL 21
+1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21
Warnings:
-Note 1003 select high_priority dimension(test.geo.g) AS `Dimension(g)`,geometrytype(test.geo.g) AS `GeometryType(g)`,isempty(test.geo.g) AS `IsEmpty(g)`,astext(envelope(test.geo.g)) AS `AsText(Envelope(g))` from test.geo
-SELECT fid, X(g) FROM pt;
+Note 1003 select high_priority dimension(test.gis_geometry.g) AS `Dimension(g)`,geometrytype(test.gis_geometry.g) AS `GeometryType(g)`,isempty(test.gis_geometry.g) AS `IsEmpty(g)`,astext(envelope(test.gis_geometry.g)) AS `AsText(Envelope(g))` from test.gis_geometry
+SELECT fid, X(g) FROM gis_point;
fid X(g)
101 10
102 20
103 20
104 10
-SELECT fid, Y(g) FROM pt;
+SELECT fid, Y(g) FROM gis_point;
fid Y(g)
101 10
102 10
103 20
104 20
-explain extended select X(g),Y(g) FROM pt;
+explain extended select X(g),Y(g) FROM gis_point;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE pt ALL NULL NULL NULL NULL 4
+1 SIMPLE gis_point ALL NULL NULL NULL NULL 4
Warnings:
-Note 1003 select high_priority x(test.pt.g) AS `X(g)`,y(test.pt.g) AS `Y(g)` from test.pt
-SELECT fid, AsText(StartPoint(g)) FROM ls;
+Note 1003 select high_priority x(test.gis_point.g) AS `X(g)`,y(test.gis_point.g) AS `Y(g)` from test.gis_point
+SELECT fid, AsText(StartPoint(g)) FROM gis_line;
fid AsText(StartPoint(g))
105 POINT(0 0)
106 POINT(10 10)
107 POINT(10 10)
-SELECT fid, AsText(EndPoint(g)) FROM ls;
+SELECT fid, AsText(EndPoint(g)) FROM gis_line;
fid AsText(EndPoint(g))
105 POINT(10 0)
106 POINT(10 10)
107 POINT(40 10)
-SELECT fid, GLength(g) FROM ls;
+SELECT fid, GLength(g) FROM gis_line;
fid GLength(g)
105 24.142135623731
106 40
107 30
-SELECT fid, NumPoints(g) FROM ls;
+SELECT fid, NumPoints(g) FROM gis_line;
fid NumPoints(g)
105 3
106 5
107 2
-SELECT fid, AsText(PointN(g, 2)) FROM ls;
+SELECT fid, AsText(PointN(g, 2)) FROM gis_line;
fid AsText(PointN(g, 2))
105 POINT(0 10)
106 POINT(20 10)
107 POINT(40 10)
-SELECT fid, IsClosed(g) FROM ls;
+SELECT fid, IsClosed(g) FROM gis_line;
fid IsClosed(g)
105 0
106 1
107 0
-explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM ls;
+explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE ls ALL NULL NULL NULL NULL 3
+1 SIMPLE gis_line ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select high_priority astext(startpoint(test.ls.g)) AS `AsText(StartPoint(g))`,astext(endpoint(test.ls.g)) AS `AsText(EndPoint(g))`,glength(test.ls.g) AS `GLength(g)`,numpoints(test.ls.g) AS `NumPoints(g)`,astext(pointn(test.ls.g,2)) AS `AsText(PointN(g, 2))`,isclosed(test.ls.g) AS `IsClosed(g)` from test.ls
-SELECT fid, AsText(Centroid(g)) FROM p;
+Note 1003 select high_priority astext(startpoint(test.gis_line.g)) AS `AsText(StartPoint(g))`,astext(endpoint(test.gis_line.g)) AS `AsText(EndPoint(g))`,glength(test.gis_line.g) AS `GLength(g)`,numpoints(test.gis_line.g) AS `NumPoints(g)`,astext(pointn(test.gis_line.g,2)) AS `AsText(PointN(g, 2))`,isclosed(test.gis_line.g) AS `IsClosed(g)` from test.gis_line
+SELECT fid, AsText(Centroid(g)) FROM gis_polygon;
fid AsText(Centroid(g))
108 POINT(15 15)
109 POINT(25.416666666667 25.416666666667)
110 POINT(20 10)
-SELECT fid, Area(g) FROM p;
+SELECT fid, Area(g) FROM gis_polygon;
fid Area(g)
108 100
109 2400
110 450
-SELECT fid, AsText(ExteriorRing(g)) FROM p;
+SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon;
fid AsText(ExteriorRing(g))
108 LINESTRING(10 10,20 10,20 20,10 20,10 10)
109 LINESTRING(0 0,50 0,50 50,0 50,0 0)
110 LINESTRING(0 0,30 0,30 30,0 0)
-SELECT fid, NumInteriorRings(g) FROM p;
+SELECT fid, NumInteriorRings(g) FROM gis_polygon;
fid NumInteriorRings(g)
108 0
109 1
110 0
-SELECT fid, AsText(InteriorRingN(g, 1)) FROM p;
+SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon;
fid AsText(InteriorRingN(g, 1))
108 NULL
109 LINESTRING(10 10,20 10,20 20,10 20,10 10)
110 NULL
-explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM p;
+explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE p ALL NULL NULL NULL NULL 3
+1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select high_priority astext(centroid(test.p.g)) AS `AsText(Centroid(g))`,area(test.p.g) AS `Area(g)`,astext(exteriorring(test.p.g)) AS `AsText(ExteriorRing(g))`,numinteriorrings(test.p.g) AS `NumInteriorRings(g)`,astext(interiorringn(test.p.g,1)) AS `AsText(InteriorRingN(g, 1))` from test.p
-SELECT fid, IsClosed(g) FROM mls;
+Note 1003 select high_priority astext(centroid(test.gis_polygon.g)) AS `AsText(Centroid(g))`,area(test.gis_polygon.g) AS `Area(g)`,astext(exteriorring(test.gis_polygon.g)) AS `AsText(ExteriorRing(g))`,numinteriorrings(test.gis_polygon.g) AS `NumInteriorRings(g)`,astext(interiorringn(test.gis_polygon.g,1)) AS `AsText(InteriorRingN(g, 1))` from test.gis_polygon
+SELECT fid, IsClosed(g) FROM gis_multi_line;
fid IsClosed(g)
114 0
115 0
116 0
-SELECT fid, AsText(Centroid(g)) FROM mp;
+SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
fid AsText(Centroid(g))
117 POINT(55.588527753042 17.426536064114)
118 POINT(55.588527753042 17.426536064114)
119 POINT(2 2)
-SELECT fid, Area(g) FROM mp;
+SELECT fid, Area(g) FROM gis_multi_polygon;
fid Area(g)
117 1684.5
118 1684.5
119 4.5
-SELECT fid, NumGeometries(g) from mpt;
+SELECT fid, NumGeometries(g) from gis_multi_point;
fid NumGeometries(g)
111 4
112 4
113 2
-SELECT fid, NumGeometries(g) from mls;
+SELECT fid, NumGeometries(g) from gis_multi_line;
fid NumGeometries(g)
114 2
115 1
116 2
-SELECT fid, NumGeometries(g) from mp;
+SELECT fid, NumGeometries(g) from gis_multi_polygon;
fid NumGeometries(g)
117 2
118 2
119 1
-SELECT fid, NumGeometries(g) from gc;
+SELECT fid, NumGeometries(g) from gis_geometrycollection;
fid NumGeometries(g)
120 2
121 2
-explain extended SELECT fid, NumGeometries(g) from mpt;
+explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE mpt ALL NULL NULL NULL NULL 3
+1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select high_priority test.mpt.fid AS `fid`,numgeometries(test.mpt.g) AS `NumGeometries(g)` from test.mpt
-SELECT fid, AsText(GeometryN(g, 2)) from mpt;
+Note 1003 select high_priority test.gis_multi_point.fid AS `fid`,numgeometries(test.gis_multi_point.g) AS `NumGeometries(g)` from test.gis_multi_point
+SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
fid AsText(GeometryN(g, 2))
111 POINT(10 10)
112 POINT(11 11)
113 POINT(4 10)
-SELECT fid, AsText(GeometryN(g, 2)) from mls;
+SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line;
fid AsText(GeometryN(g, 2))
114 LINESTRING(16 0,16 23,16 48)
115 NULL
116 LINESTRING(2 5,5 8,21 7)
-SELECT fid, AsText(GeometryN(g, 2)) from mp;
+SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon;
fid AsText(GeometryN(g, 2))
117 POLYGON((59 18,67 18,67 13,59 13,59 18))
118 POLYGON((59 18,67 18,67 13,59 13,59 18))
119 NULL
-SELECT fid, AsText(GeometryN(g, 2)) from gc;
+SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection;
fid AsText(GeometryN(g, 2))
120 LINESTRING(0 0,10 10)
121 LINESTRING(3 6,7 9)
-explain extended SELECT fid, AsText(GeometryN(g, 2)) from mpt;
+SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection;
+fid AsText(GeometryN(g, 1))
+120 POINT(0 0)
+121 POINT(44 6)
+explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE mpt ALL NULL NULL NULL NULL 3
+1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select high_priority test.mpt.fid AS `fid`,astext(geometryn(test.mpt.g,2)) AS `AsText(GeometryN(g, 2))` from test.mpt
+Note 1003 select high_priority test.gis_multi_point.fid AS `fid`,astext(geometryn(test.gis_multi_point.g,2)) AS `AsText(GeometryN(g, 2))` from test.gis_multi_point
SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
-FROM gc g1, gc g2 ORDER BY first, second;
+FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
first second w c o e d t i r
120 120 1 1 0 1 0 0 1 0
120 121 0 0 0 0 0 0 1 0
@@ -388,46 +392,46 @@ explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
-FROM gc g1, gc g2 ORDER BY first, second;
+FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
1 SIMPLE g2 ALL NULL NULL NULL NULL 2
Warnings:
-Note 1003 select high_priority test.g1.fid AS `first`,test.g2.fid AS `second`,within(test.g1.g,test.g2.g) AS `w`,contains(test.g1.g,test.g2.g) AS `c`,overlaps(test.g1.g,test.g2.g) AS `o`,equals(test.g1.g,test.g2.g) AS `e`,disjoint(test.g1.g,test.g2.g) AS `d`,touches(test.g1.g,test.g2.g) AS `t`,intersects(test.g1.g,test.g2.g) AS `i`,crosses(test.g1.g,test.g2.g) AS `r` from test.gc g1 join test.gc g2 order by test.g1.fid,test.g2.fid
-DROP TABLE pt, ls, p, mpt, mls, mp, gc, geo;
-CREATE TABLE g1 (
-pt point,
+Note 1003 select high_priority test.g1.fid AS `first`,test.g2.fid AS `second`,within(test.g1.g,test.g2.g) AS `w`,contains(test.g1.g,test.g2.g) AS `c`,overlaps(test.g1.g,test.g2.g) AS `o`,equals(test.g1.g,test.g2.g) AS `e`,disjoint(test.g1.g,test.g2.g) AS `d`,touches(test.g1.g,test.g2.g) AS `t`,intersects(test.g1.g,test.g2.g) AS `i`,crosses(test.g1.g,test.g2.g) AS `r` from test.gis_geometrycollection g1 join test.gis_geometrycollection g2 order by test.g1.fid,test.g2.fid
+DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
+CREATE TABLE t1 (
+gp point,
ln linestring,
pg polygon,
-mpt multipoint,
+mp multipoint,
mln multilinestring,
mpg multipolygon,
gc geometrycollection,
gm geometry
);
-SHOW FIELDS FROM g1;
+SHOW FIELDS FROM t1;
Field Type Null Key Default Extra
-pt point YES NULL
+gp point YES NULL
ln linestring YES NULL
pg polygon YES NULL
-mpt multipoint YES NULL
+mp multipoint YES NULL
mln multilinestring YES NULL
mpg multipolygon YES NULL
gc geometrycollection YES NULL
gm geometry YES NULL
-ALTER TABLE g1 ADD fid INT NOT NULL;
-SHOW FIELDS FROM g1;
+ALTER TABLE t1 ADD fid INT NOT NULL;
+SHOW FIELDS FROM t1;
Field Type Null Key Default Extra
-pt point YES NULL
+gp point YES NULL
ln linestring YES NULL
pg polygon YES NULL
-mpt multipoint YES NULL
+mp multipoint YES NULL
mln multilinestring YES NULL
mpg multipolygon YES NULL
gc geometrycollection YES NULL
gm geometry YES NULL
fid int(11) 0
-DROP TABLE g1;
+DROP TABLE t1;
SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))));
AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))))
POINT(1 4)
@@ -454,3 +458,11 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select high_priority issimple(multipoint(point(3,6),point(4,10))) AS `issimple(MultiPoint(Point(3, 6), Point(4, 10)))`,issimple(point(3,6)) AS `issimple(Point(3, 6))`
+create table t1 (a geometry not null);
+insert into t1 values (GeomFromText('Point(1 2)'));
+insert into t1 values ('Garbage');
+ERROR HY000: Unknown error
+insert IGNORE into t1 values ('Garbage');
+ERROR HY000: Unknown error
+alter table t1 add spatial index(a);
+drop table t1;
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index ffaf2a83b78..2c17373bd00 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -146,6 +146,37 @@ Grants for drop_user@localhost
GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
GRANT ALL PRIVILEGES ON `test`.* TO 'drop_user'@'localhost' WITH GRANT OPTION
GRANT SELECT (a) ON `test`.`t1` TO 'drop_user'@'localhost'
+set sql_mode=ansi_quotes;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON "test".* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON "test"."t1" TO 'drop_user'@'localhost'
+set sql_mode=default;
+set sql_quote_show_create=0;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON test.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON test.t1 TO 'drop_user'@'localhost'
+set sql_mode="ansi_quotes";
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON test.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON test.t1 TO 'drop_user'@'localhost'
+set sql_quote_show_create=1;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON "test".* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON "test"."t1" TO 'drop_user'@'localhost'
+set sql_mode="";
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON `test`.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON `test`.`t1` TO 'drop_user'@'localhost'
revoke all privileges, grant option from drop_user@localhost;
show grants for drop_user@localhost;
Grants for drop_user@localhost
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 38e08d7fbc5..782a71e83d1 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -86,3 +86,242 @@ use mysqltest;
create table t1 (c int);
insert into mysqltest.t1 set mysqltest.t1.c = '1';
drop database mysqltest;
+use test;
+create table t1(number int auto_increment primary key, original_value varchar(50), f_double double, f_float float, f_double_7_2 double(7,2), f_float_4_3 float (4,3), f_double_u double unsigned, f_float_u float unsigned, f_double_15_1_u double(15,1) unsigned, f_float_3_1_u float (3,1) unsigned);
+set @value= "aa";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1265 Data truncated for column 'f_double' at row 1
+Warning 1265 Data truncated for column 'f_float' at row 1
+Warning 1265 Data truncated for column 'f_double_7_2' at row 1
+Warning 1265 Data truncated for column 'f_float_4_3' at row 1
+Warning 1265 Data truncated for column 'f_double_u' at row 1
+Warning 1265 Data truncated for column 'f_float_u' at row 1
+Warning 1265 Data truncated for column 'f_double_15_1_u' at row 1
+Warning 1265 Data truncated for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 1
+original_value aa
+f_double 0
+f_float 0
+f_double_7_2 0.00
+f_float_4_3 0.000
+f_double_u 0
+f_float_u 0
+f_double_15_1_u 0.0
+f_float_3_1_u 0.0
+set @value= "1aa";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1265 Data truncated for column 'f_double' at row 1
+Warning 1265 Data truncated for column 'f_float' at row 1
+Warning 1265 Data truncated for column 'f_double_7_2' at row 1
+Warning 1265 Data truncated for column 'f_float_4_3' at row 1
+Warning 1265 Data truncated for column 'f_double_u' at row 1
+Warning 1265 Data truncated for column 'f_float_u' at row 1
+Warning 1265 Data truncated for column 'f_double_15_1_u' at row 1
+Warning 1265 Data truncated for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 2
+original_value 1aa
+f_double 1
+f_float 1
+f_double_7_2 1.00
+f_float_4_3 1.000
+f_double_u 1
+f_float_u 1
+f_double_15_1_u 1.0
+f_float_3_1_u 1.0
+set @value= "aa1";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1265 Data truncated for column 'f_double' at row 1
+Warning 1265 Data truncated for column 'f_float' at row 1
+Warning 1265 Data truncated for column 'f_double_7_2' at row 1
+Warning 1265 Data truncated for column 'f_float_4_3' at row 1
+Warning 1265 Data truncated for column 'f_double_u' at row 1
+Warning 1265 Data truncated for column 'f_float_u' at row 1
+Warning 1265 Data truncated for column 'f_double_15_1_u' at row 1
+Warning 1265 Data truncated for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 3
+original_value aa1
+f_double 0
+f_float 0
+f_double_7_2 0.00
+f_float_4_3 0.000
+f_double_u 0
+f_float_u 0
+f_double_15_1_u 0.0
+f_float_3_1_u 0.0
+set @value= "1e+1111111111a";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1265 Data truncated for column 'f_double' at row 1
+Warning 1265 Data truncated for column 'f_float' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float' at row 1
+Warning 1265 Data truncated for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
+Warning 1265 Data truncated for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
+Warning 1265 Data truncated for column 'f_double_u' at row 1
+Warning 1265 Data truncated for column 'f_float_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
+Warning 1265 Data truncated for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
+Warning 1265 Data truncated for column 'f_float_3_1_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 4
+original_value 1e+1111111111a
+f_double 1.79769313486232e+308
+f_float 3.40282e+38
+f_double_7_2 99999.99
+f_float_4_3 9.999
+f_double_u 1.79769313486232e+308
+f_float_u 3.40282e+38
+f_double_15_1_u 99999999999999.9
+f_float_3_1_u 99.9
+set @value= "-1e+1111111111a";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1265 Data truncated for column 'f_double' at row 1
+Warning 1265 Data truncated for column 'f_float' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float' at row 1
+Warning 1265 Data truncated for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
+Warning 1265 Data truncated for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
+Warning 1265 Data truncated for column 'f_double_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_u' at row 1
+Warning 1265 Data truncated for column 'f_float_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
+Warning 1265 Data truncated for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
+Warning 1265 Data truncated for column 'f_float_3_1_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 5
+original_value -1e+1111111111a
+f_double -1.79769313486232e+308
+f_float -3.40282e+38
+f_double_7_2 -99999.99
+f_float_4_3 -9.999
+f_double_u 0
+f_float_u 0
+f_double_15_1_u 0.0
+f_float_3_1_u 0.0
+set @value= 1e+1111111111;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1264 Data truncated, out of range for column 'f_float' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 6
+original_value 1.7976931348623e+308
+f_double 1.79769313486232e+308
+f_float 3.40282e+38
+f_double_7_2 99999.99
+f_float_4_3 9.999
+f_double_u 1.79769313486232e+308
+f_float_u 3.40282e+38
+f_double_15_1_u 99999999999999.9
+f_float_3_1_u 99.9
+set @value= -1e+1111111111;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1264 Data truncated, out of range for column 'f_float' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 7
+original_value -1.7976931348623e+308
+f_double -1.79769313486232e+308
+f_float -3.40282e+38
+f_double_7_2 -99999.99
+f_float_4_3 -9.999
+f_double_u 0
+f_float_u 0
+f_double_15_1_u 0.0
+f_float_3_1_u 0.0
+set @value= 1e+111;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1264 Data truncated, out of range for column 'f_float' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 8
+original_value 1e+111
+f_double 1e+111
+f_float 3.40282e+38
+f_double_7_2 99999.99
+f_float_4_3 9.999
+f_double_u 1e+111
+f_float_u 3.40282e+38
+f_double_15_1_u 99999999999999.9
+f_float_3_1_u 99.9
+set @value= -1e+111;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1264 Data truncated, out of range for column 'f_float' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 9
+original_value -1e+111
+f_double -1e+111
+f_float -3.40282e+38
+f_double_7_2 -99999.99
+f_float_4_3 -9.999
+f_double_u 0
+f_float_u 0
+f_double_15_1_u 0.0
+f_float_3_1_u 0.0
+set @value= 1;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+select * from t1 where number =last_insert_id();
+number 10
+original_value 1
+f_double 1
+f_float 1
+f_double_7_2 1.00
+f_float_4_3 1.000
+f_double_u 1
+f_float_u 1
+f_double_15_1_u 1.0
+f_float_3_1_u 1.0
+set @value= -1;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+Warnings:
+Warning 1264 Data truncated, out of range for column 'f_double_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+select * from t1 where number =last_insert_id();
+number 11
+original_value -1
+f_double -1
+f_float -1
+f_double_7_2 -1.00
+f_float_4_3 -1.000
+f_double_u 0
+f_float_u 0
+f_double_15_1_u 0.0
+f_float_3_1_u 0.0
+drop table t1;
diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result
index 3a7679ce1e3..53867bf4546 100644
--- a/mysql-test/r/insert_update.result
+++ b/mysql-test/r/insert_update.result
@@ -67,3 +67,41 @@ id select_type table type possible_keys key key_len ref rows Extra
Warnings:
Note 1003 select high_priority test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1
DROP TABLE t1;
+create table t1(a int primary key, b int);
+insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5);
+select * from t1;
+a b
+1 1
+2 2
+3 3
+4 4
+5 5
+insert into t1 values(4,14),(5,15),(6,16),(7,17),(8,18)
+on duplicate key update b=b+10;
+affected rows: 7
+info: Records: 5 Duplicates: 2 Warnings: 0
+select * from t1;
+a b
+1 1
+2 2
+3 3
+4 14
+5 15
+6 16
+7 17
+8 18
+replace into t1 values(5,25),(6,26),(7,27),(8,28),(9,29);
+affected rows: 9
+info: Records: 5 Duplicates: 4 Warnings: 0
+select * from t1;
+a b
+1 1
+2 2
+3 3
+4 14
+5 25
+6 26
+7 27
+8 28
+9 29
+drop table t1;
diff --git a/mysql-test/r/lowercase0.require b/mysql-test/r/lowercase0.require
new file mode 100644
index 00000000000..a63906557f8
--- /dev/null
+++ b/mysql-test/r/lowercase0.require
@@ -0,0 +1,3 @@
+Variable_name Value
+lower_case_file_system ON
+lower_case_table_names 0
diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result
index 0ba4a4be945..8bf3db8cad0 100644
--- a/mysql-test/r/lowercase_table.result
+++ b/mysql-test/r/lowercase_table.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2,t3,t4,T1;
+drop table if exists t1,t2,t3,t4;
create table T1 (id int primary key, Word varchar(40) not null, Index(Word));
create table t4 (id int primary key, Word varchar(40) not null);
INSERT INTO T1 VALUES (1, 'a'), (2, 'b'), (3, 'c');
@@ -42,3 +42,19 @@ select count(bags.a) from t1 as Bags;
count(bags.a)
0
drop table t1;
+create table t1 (a int);
+create table t2 (a int);
+delete p1.*,P2.* from t1 as p1, t2 as p2 where p1.a=P2.a;
+delete P1.*,p2.* from t1 as P1, t2 as P2 where P1.a=p2.a;
+update t1 as p1, t2 as p2 SET p1.a=1,P2.a=1 where p1.a=P2.a;
+update t1 as P1, t2 as P2 SET P1.a=1,p2.a=1 where P1.a=p2.a;
+drop table t1,t2;
+create table t1 (a int);
+create table t2 (a int);
+select * from t1 c, t2 C;
+ERROR 42000: Not unique table/alias: 'C'
+select C.a, c.a from t1 c, t2 C;
+ERROR 42000: Not unique table/alias: 'C'
+drop table t1, t2;
+show tables;
+Tables_in_test
diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result
index e582978c126..737d49fc340 100644
--- a/mysql-test/r/lowercase_table2.result
+++ b/mysql-test/r/lowercase_table2.result
@@ -106,3 +106,18 @@ SELECT * from T1;
a
1
DROP TABLE T1;
+create table T1 (EVENT_ID int auto_increment primary key, LOCATION char(20));
+insert into T1 values (NULL,"Mic-4"),(NULL,"Mic-5"),(NULL,"Mic-6");
+SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
+LOCATION
+Mic-5
+Mic-6
+SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
+LOCATION
+Mic-5
+Mic-6
+SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
+LOCATION
+Mic-5
+Mic-6
+drop table T1;
diff --git a/mysql-test/r/lowercase_table3.result b/mysql-test/r/lowercase_table3.result
new file mode 100644
index 00000000000..362d17e0461
--- /dev/null
+++ b/mysql-test/r/lowercase_table3.result
@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS t1,T1;
+CREATE TABLE t1 (a int);
+SELECT * from T1;
+a
+drop table t1;
+flush tables;
+CREATE TABLE t1 (a int) type=INNODB;
+SELECT * from T1;
+Can't open file: 'T1.InnoDB'. (errno: 1)
+drop table t1;
diff --git a/mysql-test/r/lowercase_table_qcache.result b/mysql-test/r/lowercase_table_qcache.result
new file mode 100644
index 00000000000..f8d34e0f592
--- /dev/null
+++ b/mysql-test/r/lowercase_table_qcache.result
@@ -0,0 +1,24 @@
+set GLOBAL query_cache_size=1355776;
+drop database if exists MySQLtesT;
+create database MySQLtesT;
+create table MySQLtesT.t1 (a int);
+select * from MySQLtesT.t1;
+a
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+drop database mysqltest;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+use MySQL;
+select * from db;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+use test;
+select * from MySQL.db;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+set GLOBAL query_cache_size=0;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index a61ce31b8ae..fc5ef88f045 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -396,3 +396,42 @@ select 't1 rows after big delete', count(*) from t1;
t1 rows after big delete count(*)
t1 rows after big delete 1900001
drop table t1,t2;
+CREATE TABLE t1 ( a int );
+CREATE TABLE t2 ( a int );
+DELETE t1 FROM t1, t2 AS t3;
+DELETE t4 FROM t1, t1 AS t4;
+DELETE t3 FROM t1 AS t3, t1 AS t4;
+DELETE t1 FROM t1 AS t3, t2 AS t4;
+ERROR 42000: Not unique table/alias: 't1'
+INSERT INTO t1 values (1),(2);
+INSERT INTO t2 values (1),(2);
+DELETE t1 FROM t1 AS t2, t2 AS t1 where t1.a=t2.a and t1.a=1;
+SELECT * from t1;
+a
+1
+2
+SELECT * from t2;
+a
+2
+DELETE t2 FROM t1 AS t2, t2 AS t1 where t1.a=t2.a and t1.a=2;
+SELECT * from t1;
+a
+1
+SELECT * from t2;
+a
+2
+DROP TABLE t1,t2;
+create table `t1` (`p_id` int(10) unsigned NOT NULL auto_increment, `p_code` varchar(20) NOT NULL default '', `p_active` tinyint(1) unsigned NOT NULL default '1', PRIMARY KEY (`p_id`) );
+create table `t2` (`c2_id` int(10) unsigned NULL auto_increment, `c2_p_id` int(10) unsigned NOT NULL default '0', `c2_note` text NOT NULL, `c2_active` tinyint(1) unsigned NOT NULL default '1', PRIMARY KEY (`c2_id`), KEY `c2_p_id` (`c2_p_id`) );
+insert into t1 values (0,'A01-Comp',1);
+insert into t1 values (0,'B01-Comp',1);
+insert into t2 values (0,1,'A Note',1);
+update t1 left join t2 on p_id = c2_p_id set c2_note = 'asdf-1' where p_id = 2;
+select * from t1;
+p_id p_code p_active
+1 A01-Comp 1
+2 B01-Comp 1
+select * from t2;
+c2_id c2_p_id c2_note c2_active
+1 1 A Note 1
+drop table t1, t2;
diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result
index f70eaeae214..5592524cc39 100644
--- a/mysql-test/r/mysqlbinlog.result
+++ b/mysql-test/r/mysqlbinlog.result
@@ -14,6 +14,7 @@ insert into t1 values ("Alas");
flush logs;
--- Local --
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
use test;
SET TIMESTAMP=1000000000;
create table t1 (word varchar(20));
@@ -31,19 +32,23 @@ LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-4-0' INTO TABLE `t1` FI
LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-5-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
--- Broken LOAD DATA --
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
use test;
SET TIMESTAMP=1000000000;
insert into t1 values ("Alas");
--- --database --
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
SET INSERT_ID=1;
--- --position --
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
use test;
SET TIMESTAMP=1000000000;
insert into t1 values ("Alas");
--- Remote --
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
use test;
SET TIMESTAMP=1000000000;
create table t1 (word varchar(20));
@@ -59,19 +64,19 @@ LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-2-1' INTO TABLE `t1` FI
LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-3-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-4-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-5-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-6-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-SET TIMESTAMP=1000000000;
-insert into t1 values ("Alas");
--- Broken LOAD DATA --
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
use test;
SET TIMESTAMP=1000000000;
insert into t1 values ("Alas");
--- --database --
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
SET INSERT_ID=1;
--- --position --
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
use test;
SET TIMESTAMP=1000000000;
insert into t1 values ("Alas");
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index fe1b83a1089..b0a15d9a021 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -142,7 +142,7 @@ CREATE TABLE t1 (a int) ENGINE=MYISAM;
INSERT INTO t1 VALUES (1), (2);
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO,MYSQL40" */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` int(11) default NULL
@@ -161,7 +161,7 @@ UNLOCK TABLES;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO,MYSQL323" */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` int(11) default NULL
@@ -203,6 +203,88 @@ UNLOCK TABLES;
drop table ```a`;
create table t1(a int);
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO" */;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO,ANSI" */;
+DROP TABLE IF EXISTS "t1";
+CREATE TABLE "t1" (
+ "a" int(11) default NULL
+);
+
+
+/*!40000 ALTER TABLE "t1" DISABLE KEYS */;
+LOCK TABLES "t1" WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE "t1" ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+
+set global sql_mode='ANSI_QUOTES';
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO" */;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO,ANSI" */;
+DROP TABLE IF EXISTS "t1";
+CREATE TABLE "t1" (
+ "a" int(11) default NULL
+);
+
+
+/*!40000 ALTER TABLE "t1" DISABLE KEYS */;
+LOCK TABLES "t1" WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE "t1" ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+
+set global sql_mode='';
+drop table t1;
+create table t1(a int);
insert into t1 values (1),(2),(3);
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 4033996b239..006b507d409 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -611,3 +611,35 @@ a b
5 2
6 2
drop table t1;
+create table t1 (a int not null auto_increment, b int not null, c int not null, d int not null,
+key(a,b,d), key(c,b,a));
+create table t2 like t1;
+insert into t1 values (NULL, 1, 2, 0), (NULL, 2, 1, 1), (NULL, 3, 4, 2), (NULL, 4, 3, 3);
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+set @row=10;
+insert into t1 select 1, b, c + (@row:=@row - 1) * 10, d - @row from t2 limit 10;
+select * from t1 where a=1 and b in (1) order by c, b, a;
+a b c d
+1 1 2 0
+1 1 12 -1
+1 1 52 -5
+1 1 92 -9
+select * from t1 where a=1 and b in (1);
+a b c d
+1 1 92 -9
+1 1 52 -5
+1 1 12 -1
+1 1 2 0
+drop table t1, t2;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 5bbf0bad445..85bc50ef708 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -774,6 +774,23 @@ select * from t3;
delete from t4 where a=1;
flush query cache;
drop table t1,t2,t3,t4;
+set query_cache_wlock_invalidate=1;
+create table t1 (a int not null);
+create table t2 (a int not null);
+select * from t1;
+a
+select * from t2;
+a
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+lock table t1 write, t2 read;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+unlock table;
+drop table t1,t2;
+set query_cache_wlock_invalidate=default;
SET NAMES koi8r;
CREATE TABLE t1 (a char(1) character set koi8r);
INSERT INTO t1 VALUES (_koi8r'á'),(_koi8r'Á');
diff --git a/mysql-test/r/rpl000009.result b/mysql-test/r/rpl000009.result
index 1f78a505280..bb82dcb1e6a 100644
--- a/mysql-test/r/rpl000009.result
+++ b/mysql-test/r/rpl000009.result
@@ -112,6 +112,18 @@ n s
2 two test
3 three test
4 four test
+stop slave;
+reset slave;
+load data from master;
+start slave;
+insert into mysqltest.t1 values (5, 'five bar');
+select * from mysqltest.t1;
+n s
+1 one test
+2 two test
+3 three test
+4 four test
+5 five bar
load table mysqltest.t1 from master;
ERROR 42S01: Table 't1' already exists
drop table mysqltest.t1;
diff --git a/mysql-test/r/rpl_error_ignored_table.result b/mysql-test/r/rpl_error_ignored_table.result
index 8d5bbf91561..dd277e41ad0 100644
--- a/mysql-test/r/rpl_error_ignored_table.result
+++ b/mysql-test/r/rpl_error_ignored_table.result
@@ -9,7 +9,32 @@ insert into t1 values (1),(1);
ERROR 23000: Duplicate entry '1' for key 1
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 213 slave-relay-bin.000002 257 master-bin.000001 Yes Yes test.t1 0 0 213 257 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 213 slave-relay-bin.000002 257 master-bin.000001 Yes Yes test.t3,test.t1,test.t2 0 0 213 257 None 0 No #
show tables like 't1';
Tables_in_test (t1)
drop table t1;
+select get_lock('crash_lock%20C', 10);
+get_lock('crash_lock%20C', 10)
+1
+create table t2 (a int primary key);
+insert into t2 values(1);
+create table t3 (id int);
+insert into t3 values(connection_id());
+ update t2 set a = a + 1 + get_lock('crash_lock%20C', 10);
+select (@id := id) - id from t3;
+(@id := id) - id
+0
+kill @id;
+drop table t2,t3;
+Got one of the listed errors
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.000001 79 Query 1 79 use `test`; create table t1 (a int primary key)
+master-bin.000001 149 Query 1 149 use `test`; insert into t1 values (1),(1)
+master-bin.000001 213 Query 1 213 use `test`; drop table t1
+master-bin.000001 261 Query 1 261 use `test`; create table t2 (a int primary key)
+master-bin.000001 331 Query 1 331 use `test`; insert into t2 values(1)
+master-bin.000001 390 Query 1 390 use `test`; create table t3 (id int)
+master-bin.000001 449 Query 1 449 use `test`; insert into t3 values(connection_id())
+master-bin.000001 522 Query 1 522 use `test`; update t2 set a = a + 1 + get_lock('crash_lock%20C', 10)
+master-bin.000001 613 Query 1 613 use `test`; drop table t2,t3
diff --git a/mysql-test/r/rpl_optimize.result b/mysql-test/r/rpl_optimize.result
new file mode 100644
index 00000000000..79891169fbc
--- /dev/null
+++ b/mysql-test/r/rpl_optimize.result
@@ -0,0 +1,27 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create table t1 (a int not null auto_increment primary key, b int, key(b));
+INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+update t1 set b=(a/2*rand());
+delete from t1 order by b limit 10000;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+drop table t1;
diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result
index 39b754dec47..ad0fb9e5022 100644
--- a/mysql-test/r/rpl_trunc_binlog.result
+++ b/mysql-test/r/rpl_trunc_binlog.result
@@ -10,4 +10,4 @@ reset slave;
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 slave-relay-bin.000002 123 master-bin.000001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 326 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 slave-relay-bin.000002 123 master-bin.000001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. A probable cause is that the master died while writing the transaction to its binary log. 0 79 326 None 0 No #
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 2dc715f238f..3693d92693f 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -89,8 +89,8 @@ create table t1 (
test_set set( 'val1', 'val2', 'val3' ) not null default '',
name char(20) default 'O''Brien' comment 'O''Brien as default',
c int not null comment 'int column',
-`c-b` int comment 'name with a space',
-`space ` int comment 'name with a space',
+`c-b` int comment 'name with a minus',
+`space 2` int comment 'name with a space',
) comment = 'it\'s a table' ;
show create table t1;
Table Create Table
@@ -98,8 +98,8 @@ t1 CREATE TABLE `t1` (
`test_set` set('val1','val2','val3') NOT NULL default '',
`name` char(20) default 'O''Brien' COMMENT 'O''Brien as default',
`c` int(11) NOT NULL default '0' COMMENT 'int column',
- `c-b` int(11) default NULL COMMENT 'name with a space',
- `space ` int(11) default NULL COMMENT 'name with a space'
+ `c-b` int(11) default NULL COMMENT 'name with a minus',
+ `space 2` int(11) default NULL COMMENT 'name with a space'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='it''s a table'
set sql_quote_show_create=0;
show create table t1;
@@ -108,8 +108,8 @@ t1 CREATE TABLE t1 (
test_set set('val1','val2','val3') NOT NULL default '',
name char(20) default 'O''Brien' COMMENT 'O''Brien as default',
c int(11) NOT NULL default '0' COMMENT 'int column',
- `c-b` int(11) default NULL COMMENT 'name with a space',
- `space ` int(11) default NULL COMMENT 'name with a space'
+ `c-b` int(11) default NULL COMMENT 'name with a minus',
+ `space 2` int(11) default NULL COMMENT 'name with a space'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='it''s a table'
set sql_quote_show_create=1;
show full columns from t1;
@@ -117,8 +117,8 @@ Field Type Collation Null Key Default Extra Privileges Comment
test_set set('val1','val2','val3') latin1_swedish_ci select,insert,update,references
name char(20) latin1_swedish_ci YES O'Brien select,insert,update,references O'Brien as default
c int(11) NULL 0 select,insert,update,references int column
-c-b int(11) NULL YES NULL select,insert,update,references name with a space
-space int(11) NULL YES NULL select,insert,update,references name with a space
+c-b int(11) NULL YES NULL select,insert,update,references name with a minus
+space 2 int(11) NULL YES NULL select,insert,update,references name with a space
drop table t1;
create table t1 (a int not null, unique aa (a));
show create table t1;
@@ -265,39 +265,13 @@ c decimal(4,3) YES NULL
d double(4,3) YES NULL
f float(4,3) YES NULL
drop table t1;
-SET sql_mode='';
-SET sql_quote_show_create=OFF;
-CREATE TABLE ```ab``cd``` (i INT);
-SHOW CREATE TABLE ```ab``cd```;
-Table Create Table
-`ab`cd` CREATE TABLE ```ab``cd``` (
- i int(11) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-DROP TABLE ```ab``cd```;
-CREATE TABLE ```ab````cd``` (i INT);
-SHOW CREATE TABLE ```ab````cd```;
-Table Create Table
-`ab``cd` CREATE TABLE ```ab````cd``` (
- i int(11) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-DROP TABLE ```ab````cd```;
-CREATE TABLE ```a` (i INT);
-SHOW CREATE TABLE ```a`;
-Table Create Table
-`a CREATE TABLE ```a` (
- i int(11) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-DROP TABLE ```a`;
-SET sql_mode='ANSI_QUOTES';
-CREATE TABLE """a" (i INT);
-SHOW CREATE TABLE """a";
-Table Create Table
-"a CREATE TABLE """a" (
- i int(11) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-DROP TABLE """a";
-SET sql_mode='';
-SET sql_quote_show_create=OFF;
+SET @old_sql_mode= @@sql_mode, sql_mode= '';
+SET @old_sql_quote_show_create= @@sql_quote_show_create, sql_quote_show_create= OFF;
+CREATE TABLE `a/b` (i INT);
+ERROR 42000: Incorrect table name 'a/b'
+SET sql_mode= 'ANSI_QUOTES';
+SET sql_mode= '';
+SET sql_quote_show_create= OFF;
CREATE TABLE t1 (i INT);
SHOW CREATE TABLE t1;
Table Create Table
@@ -312,7 +286,8 @@ table CREATE TABLE `table` (
i int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE `table`;
-SET sql_quote_show_create=ON;
+SET sql_quote_show_create= @old_sql_quote_show_create;
+SET sql_mode= @old_sql_mode;
select @@max_heap_table_size;
@@max_heap_table_size
1047552
@@ -335,55 +310,55 @@ insert into t2 values (1),(2);
insert into t3 values (1,1),(2,2);
show table status;
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 2 5 39904 249415 42 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 2 5 39904 249415 39904 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 2 9 33072 248103 22090 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 HEAP Fixed 2 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP Fixed 2 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP Fixed 2 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
insert into t1 values (3),(4);
insert into t2 values (3),(4);
insert into t3 values (3,3),(4,4);
show table status;
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 4 5 39904 249415 84 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 4 5 39904 249415 39904 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 4 9 33072 248103 22132 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 HEAP Fixed 4 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP Fixed 4 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP Fixed 4 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
show table status;
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 5 5 39904 249415 105 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 5 5 39904 249415 39904 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 5 9 33072 248103 22153 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 HEAP Fixed 5 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP Fixed 5 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP Fixed 5 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1 where a=3;
delete from t2 where b=3;
delete from t3 where a=3;
show table status;
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 4 5 39904 249415 105 5 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 4 5 39904 249415 39904 5 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 4 9 33072 248103 22153 9 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 HEAP Fixed 4 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP Fixed 4 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP Fixed 4 9 # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1;
delete from t2;
delete from t3;
show table status;
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 0 5 0 249415 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 0 5 0 249415 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 0 9 0 248103 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 HEAP Fixed 0 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP Fixed 0 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP Fixed 0 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
show table status;
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 1 5 39904 249415 21 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 1 5 39904 249415 39904 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 1 9 33072 248103 22069 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 HEAP Fixed 1 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP Fixed 1 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP Fixed 1 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1 where a=5;
delete from t2 where b=5;
delete from t3 where a=5;
show table status;
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 0 5 39904 249415 21 5 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 0 5 39904 249415 39904 5 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 0 9 33072 248103 22069 9 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 HEAP Fixed 0 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP Fixed 0 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP Fixed 0 9 # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
drop table t1, t2, t3;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index ee3492c8111..9650b7bb591 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1160,9 +1160,9 @@ SELECT 0 IN (SELECT 1 FROM t1 a);
EXPLAIN EXTENDED SELECT 0 IN (SELECT 1 FROM t1 a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
-2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
-Note 1003 select high_priority <in_optimizer>(0,<exists>(select 1 AS `Not_used` from test.t1 a where isnull(1) having <is_not_null_test>(1) limit 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 select high_priority <in_optimizer>(0,<exists>(select 1 AS `Not_used` from test.t1 a limit 1)) AS `0 IN (SELECT 1 FROM t1 a)`
INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 0 IN (SELECT 1 FROM t1 a);
0 IN (SELECT 1 FROM t1 a)
@@ -1170,9 +1170,9 @@ SELECT 0 IN (SELECT 1 FROM t1 a);
EXPLAIN EXTENDED SELECT 0 IN (SELECT 1 FROM t1 a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
-2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
-Note 1003 select high_priority <in_optimizer>(0,<exists>(select 1 AS `Not_used` from test.t1 a where isnull(1) having <is_not_null_test>(1) limit 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 select high_priority <in_optimizer>(0,<exists>(select 1 AS `Not_used` from test.t1 a limit 1)) AS `0 IN (SELECT 1 FROM t1 a)`
drop table t1;
CREATE TABLE `t1` (
`i` int(11) NOT NULL default '0',
@@ -1569,6 +1569,16 @@ INSERT INTO t2 VALUES (100, 200, 'C');
SELECT DISTINCT COLC FROM t1 WHERE COLA = (SELECT COLA FROM t2 WHERE COLB = 200 AND COLC ='C' LIMIT 1);
COLC
DROP TABLE t1, t2;
+CREATE TABLE t1 (a int(1));
+INSERT INTO t1 VALUES (1),(1),(1),(1),(1),(2),(3),(4),(5);
+SELECT DISTINCT (SELECT a) FROM t1 LIMIT 100;
+(SELECT a)
+1
+2
+3
+4
+5
+DROP TABLE t1;
create table t1 (a int, b decimal(13, 3));
insert into t1 values (1, 0.123);
select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1;
@@ -1614,3 +1624,80 @@ select 2 in (select * from t1);
1
SET SQL_SELECT_LIMIT=default;
drop table t1;
+CREATE TABLE t1 (a int, b int, INDEX (a));
+INSERT INTO t1 VALUES (1, 1), (1, 2), (1, 3);
+SELECT * FROM t1 WHERE a = (SELECT MAX(a) FROM t1 WHERE a = 1) ORDER BY b;
+a b
+1 1
+1 2
+1 3
+DROP TABLE t1;
+create table t1(val varchar(10));
+insert into t1 values ('aaa'), ('bbb'),('eee'),('mmm'),('ppp');
+select count(*) from t1 as w1 where w1.val in (select w2.val from t1 as w2 where w2.val like 'm%') and w1.val in (select w3.val from t1 as w3 where w3.val like 'e%');
+count(*)
+0
+drop table t1;
+create table t1 (id int not null, text varchar(20) not null default '', primary key (id));
+insert into t1 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text11'), (12, 'text12');
+select * from t1 where id not in (select id from t1 where id < 8);
+id text
+8 text8
+9 text9
+10 text10
+11 text11
+12 text12
+select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
+id text
+8 text8
+9 text9
+10 text10
+11 text11
+12 text12
+explain extended select * from t1 where id not in (select id from t1 where id < 8);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where
+2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
+Warnings:
+Note 1003 select high_priority test.t1.id AS `id`,test.t1.text AS `text` from test.t1 where not(<in_optimizer>(test.t1.id,<exists>(<primary_index_lookup>(<cache>(test.t1.id) in t1 on PRIMARY where (test.t1.id < 8)))))
+explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY tt ALL NULL NULL NULL NULL 12 Using where
+2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 7 Using where; Using index
+Warnings:
+Note 1276 Field or reference 'tt.id' of SELECT #2 was resolved in SELECT #1
+Note 1003 select high_priority test.tt.id AS `id`,test.tt.text AS `text` from test.t1 tt where not(exists(select test.t1.id AS `id` from test.t1 where ((test.t1.id < 8) and ((test.t1.id = test.tt.id) or isnull(test.t1.id))) having (test.t1.id is not null) limit 1))
+insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
+create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
+insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
+select * from t1 a left join t2 b on (a.id=b.id or b.id is null) join t1 c on (if(isnull(b.id), 1000, b.id)=c.id);
+id text id text id text
+1 text1 1 text1 1 text1
+2 text2 2 text2 2 text2
+3 text3 3 text3 3 text3
+4 text4 4 text4 4 text4
+5 text5 5 text5 5 text5
+6 text6 6 text6 6 text6
+7 text7 7 text7 7 text7
+8 text8 8 text8 8 text8
+9 text9 9 text9 9 text9
+10 text10 10 text10 10 text10
+11 text11 11 text1 11 text11
+12 text12 12 text2 12 text12
+1000 text1000 NULL NULL 1000 text1000
+1001 text1001 NULL NULL 1000 text1000
+explain extended select * from t1 a left join t2 b on (a.id=b.id or b.id is null) join t1 c on (if(isnull(b.id), 1000, b.id)=c.id);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE a ALL NULL NULL NULL NULL 14
+1 SIMPLE b eq_ref PRIMARY PRIMARY 4 test.a.id 2
+1 SIMPLE c eq_ref PRIMARY PRIMARY 4 func 1 Using where
+Warnings:
+Note 1003 select high_priority test.a.id AS `id`,test.a.text AS `text`,test.b.id AS `id`,test.b.text AS `text`,test.c.id AS `id`,test.c.text AS `text` from test.t1 a left join test.t2 b on(((test.a.id = test.b.id) or isnull(test.b.id))) join test.t1 c where (if(isnull(test.b.id),1000,test.b.id) = test.c.id)
+drop table t1,t2;
+create table t1 (a int);
+insert into t1 values (1);
+explain select benchmark(1000, (select a from t1 where a=sha(rand())));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
+2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 1
+drop table t1;
diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result
index b04fec26c6f..c2780a08d36 100644
--- a/mysql-test/r/subselect2.result
+++ b/mysql-test/r/subselect2.result
@@ -120,9 +120,9 @@ DOCID DOCNAME DOCTYPEID FOLDERID AUTHOR CREATED TITLE SUBTITLE DOCABSTRACT PUBLI
c373e9f5ad07993f3859444553544200 Last Discussion c373e9f5ad079174ff17444553544200 c373e9f5ad0796c0eca4444553544200 Goldilocks 2003-06-09 11:21:06 Title: Last Discussion NULL Setting new abstract and keeping doc checked out 2003-06-09 10:51:26 2003-06-09 10:51:26 NULL NULL NULL 03eea05112b845949f3fd03278b5fe43 2003-06-09 11:21:06 admin 0 NULL Discussion NULL NULL
EXPLAIN SELECT t2.*, t4.DOCTYPENAME, t1.CONTENTSIZE,t1.MIMETYPE FROM t2 INNER JOIN t4 ON t2.DOCTYPEID = t4.DOCTYPEID LEFT OUTER JOIN t1 ON t2.DOCID = t1.DOCID WHERE t2.FOLDERID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t3.FOLDERNAME = 'Level1') AND t3.FOLDERNAME = 'Level2') AND t3.FOLDERNAME = 'Level3') AND t3.FOLDERNAME = 'CopiedFolder') AND t3.FOLDERNAME = 'Movie Reviews') AND t2.DOCNAME = 'Last Discussion';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 system PRIMARY NULL NULL NULL 0 const row not found
-1 PRIMARY t2 ALL DDOCTYPEID_IDX NULL NULL NULL 9 Using where
+1 PRIMARY t2 ALL DDOCTYPEID_IDX NULL NULL NULL 10 Using where
1 PRIMARY t4 eq_ref PRIMARY PRIMARY 32 test.t2.DOCTYPEID 1
+1 PRIMARY t1 eq_ref PRIMARY PRIMARY 32 test.t2.DOCID 1
2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
3 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
4 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
new file mode 100644
index 00000000000..8da46564619
--- /dev/null
+++ b/mysql-test/r/system_mysql_db.result
@@ -0,0 +1,123 @@
+show tables;
+Tables_in_db
+columns_priv
+db
+func
+help_category
+help_keyword
+help_relation
+help_topic
+host
+tables_priv
+user
+show create table db;
+Table Create Table
+db CREATE TABLE `db` (
+ `Host` char(60) binary NOT NULL default '',
+ `Db` char(64) binary NOT NULL default '',
+ `User` char(16) binary NOT NULL default '',
+ `Select_priv` enum('N','Y') NOT NULL default 'N',
+ `Insert_priv` enum('N','Y') NOT NULL default 'N',
+ `Update_priv` enum('N','Y') NOT NULL default 'N',
+ `Delete_priv` enum('N','Y') NOT NULL default 'N',
+ `Create_priv` enum('N','Y') NOT NULL default 'N',
+ `Drop_priv` enum('N','Y') NOT NULL default 'N',
+ `Grant_priv` enum('N','Y') NOT NULL default 'N',
+ `References_priv` enum('N','Y') NOT NULL default 'N',
+ `Index_priv` enum('N','Y') NOT NULL default 'N',
+ `Alter_priv` enum('N','Y') NOT NULL default 'N',
+ `Create_tmp_table_priv` enum('N','Y') NOT NULL default 'N',
+ `Lock_tables_priv` enum('N','Y') NOT NULL default 'N',
+ PRIMARY KEY (`Host`,`Db`,`User`),
+ KEY `User` (`User`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Database privileges'
+show create table host;
+Table Create Table
+host CREATE TABLE `host` (
+ `Host` char(60) binary NOT NULL default '',
+ `Db` char(64) binary NOT NULL default '',
+ `Select_priv` enum('N','Y') NOT NULL default 'N',
+ `Insert_priv` enum('N','Y') NOT NULL default 'N',
+ `Update_priv` enum('N','Y') NOT NULL default 'N',
+ `Delete_priv` enum('N','Y') NOT NULL default 'N',
+ `Create_priv` enum('N','Y') NOT NULL default 'N',
+ `Drop_priv` enum('N','Y') NOT NULL default 'N',
+ `Grant_priv` enum('N','Y') NOT NULL default 'N',
+ `References_priv` enum('N','Y') NOT NULL default 'N',
+ `Index_priv` enum('N','Y') NOT NULL default 'N',
+ `Alter_priv` enum('N','Y') NOT NULL default 'N',
+ `Create_tmp_table_priv` enum('N','Y') NOT NULL default 'N',
+ `Lock_tables_priv` enum('N','Y') NOT NULL default 'N',
+ PRIMARY KEY (`Host`,`Db`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Host privileges; Merged with database privileges'
+show create table user;
+Table Create Table
+user CREATE TABLE `user` (
+ `Host` varchar(60) binary NOT NULL default '',
+ `User` varchar(16) binary NOT NULL default '',
+ `Password` varchar(41) binary NOT NULL default '',
+ `Select_priv` enum('N','Y') NOT NULL default 'N',
+ `Insert_priv` enum('N','Y') NOT NULL default 'N',
+ `Update_priv` enum('N','Y') NOT NULL default 'N',
+ `Delete_priv` enum('N','Y') NOT NULL default 'N',
+ `Create_priv` enum('N','Y') NOT NULL default 'N',
+ `Drop_priv` enum('N','Y') NOT NULL default 'N',
+ `Reload_priv` enum('N','Y') NOT NULL default 'N',
+ `Shutdown_priv` enum('N','Y') NOT NULL default 'N',
+ `Process_priv` enum('N','Y') NOT NULL default 'N',
+ `File_priv` enum('N','Y') NOT NULL default 'N',
+ `Grant_priv` enum('N','Y') NOT NULL default 'N',
+ `References_priv` enum('N','Y') NOT NULL default 'N',
+ `Index_priv` enum('N','Y') NOT NULL default 'N',
+ `Alter_priv` enum('N','Y') NOT NULL default 'N',
+ `Show_db_priv` enum('N','Y') NOT NULL default 'N',
+ `Super_priv` enum('N','Y') NOT NULL default 'N',
+ `Create_tmp_table_priv` enum('N','Y') NOT NULL default 'N',
+ `Lock_tables_priv` enum('N','Y') NOT NULL default 'N',
+ `Execute_priv` enum('N','Y') NOT NULL default 'N',
+ `Repl_slave_priv` enum('N','Y') NOT NULL default 'N',
+ `Repl_client_priv` enum('N','Y') NOT NULL default 'N',
+ `ssl_type` enum('','ANY','X509','SPECIFIED') NOT NULL default '',
+ `ssl_cipher` blob NOT NULL,
+ `x509_issuer` blob NOT NULL,
+ `x509_subject` blob NOT NULL,
+ `max_questions` int(11) unsigned NOT NULL default '0',
+ `max_updates` int(11) unsigned NOT NULL default '0',
+ `max_connections` int(11) unsigned NOT NULL default '0',
+ PRIMARY KEY (`Host`,`User`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Users and global privileges'
+show create table func;
+Table Create Table
+func CREATE TABLE `func` (
+ `name` char(64) binary NOT NULL default '',
+ `ret` tinyint(1) NOT NULL default '0',
+ `dl` char(128) NOT NULL default '',
+ `type` enum('function','aggregate') NOT NULL default 'function',
+ PRIMARY KEY (`name`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='User defined functions'
+show create table tables_priv;
+Table Create Table
+tables_priv CREATE TABLE `tables_priv` (
+ `Host` char(60) binary NOT NULL default '',
+ `Db` char(64) binary NOT NULL default '',
+ `User` char(16) binary NOT NULL default '',
+ `Table_name` char(64) binary NOT NULL default '',
+ `Grantor` char(77) NOT NULL default '',
+ `Timestamp` timestamp NOT NULL,
+ `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') NOT NULL default '',
+ `Column_priv` set('Select','Insert','Update','References') NOT NULL default '',
+ PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`),
+ KEY `Grantor` (`Grantor`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Table privileges'
+show create table columns_priv;
+Table Create Table
+columns_priv CREATE TABLE `columns_priv` (
+ `Host` char(60) binary NOT NULL default '',
+ `Db` char(64) binary NOT NULL default '',
+ `User` char(16) binary NOT NULL default '',
+ `Table_name` char(64) binary NOT NULL default '',
+ `Column_name` char(64) binary NOT NULL default '',
+ `Timestamp` timestamp NOT NULL,
+ `Column_priv` set('Select','Insert','Update','References') NOT NULL default '',
+ PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Column privileges'
diff --git a/mysql-test/r/system_mysql_db_refs.result b/mysql-test/r/system_mysql_db_refs.result
new file mode 100644
index 00000000000..e15934b03ac
--- /dev/null
+++ b/mysql-test/r/system_mysql_db_refs.result
@@ -0,0 +1,67 @@
+set @name="This is a very long string, that mustn't find room in a system field like Table_name. Thus it should be cut by the actual size of the field. So we can use this string to find out the actual length of the field and to use it in any compare queries";
+create table test_db select * from mysql.db;
+delete from test_db;
+insert into test_db (Host,Db,User) values (@name,@name,@name);
+create table test_host select * from mysql.host;
+delete from test_host;
+insert into test_host (Host,Db) values (@name,@name);
+create table test_user select * from mysql.user;
+delete from test_user;
+insert into test_user (Host,User) values (@name,@name);
+create table test_func select * from mysql.func;
+delete from test_func;
+insert into test_func (name) values (@name);
+create table test_tables_priv select * from mysql.tables_priv;
+delete from test_tables_priv;
+insert into test_tables_priv (Host,Db,User,Table_name) values (@name,@name,@name,@name);
+create table test_columns_priv select * from mysql.columns_priv;
+delete from test_columns_priv;
+insert into test_columns_priv (Host,Db,User,Table_name,Column_name) values (@name,@name,@name,@name,@name);
+select
+if(isnull(test_db.Host),'WRONG!!!','ok') as test_db_Host,
+if(isnull(test_host.Host),'WRONG!!!','ok') as test_host_Host,
+if(isnull(test_user.Host),'WRONG!!!','ok') as test_user_Host,
+if(isnull(test_tables_priv.Host),'WRONG!!!','ok') as test_tables_priv_Host,
+if(isnull(test_columns_priv.Host),'WRONG!!!','ok') as test_columns_priv_Host
+from test_db
+left join test_host on test_db.Host=test_host.Host
+left join test_user on test_db.Host=test_user.Host
+left join test_tables_priv on test_db.Host=test_tables_priv.Host
+left join test_columns_priv on test_db.Host=test_columns_priv.Host;
+test_db_Host test_host_Host test_user_Host test_tables_priv_Host test_columns_priv_Host
+ok ok ok ok ok
+select
+if(isnull(test_db.Db),'WRONG!!!','ok') as test_db_Db,
+if(isnull(test_host.Db),'WRONG!!!','ok') as test_host_Db,
+if(isnull(test_tables_priv.Db),'WRONG!!!','ok') as test_tables_priv_Db,
+if(isnull(test_columns_priv.Db),'WRONG!!!','ok') as est_columns_priv_Db
+from test_db
+left join test_host on test_db.Db=test_host.Db
+left join test_tables_priv on test_db.Db=test_tables_priv.Db
+left join test_columns_priv on test_db.Db=test_columns_priv.Db;
+test_db_Db test_host_Db test_tables_priv_Db est_columns_priv_Db
+ok ok ok ok
+select
+if(isnull(test_db.User),'WRONG!!!','ok') as test_db_User,
+if(isnull(test_user.User),'WRONG!!!','ok') as test_user_User,
+if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User,
+if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User
+from test_db
+left join test_user on test_db.User=test_user.User
+left join test_tables_priv on test_db.User=test_tables_priv.User
+left join test_columns_priv on test_db.User=test_columns_priv.User;
+test_db_User test_user_User test_tables_priv_User test_columns_priv_User
+ok ok ok ok
+select
+if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User,
+if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User
+from test_tables_priv
+left join test_columns_priv on test_tables_priv.Table_name=test_columns_priv.Table_name;
+test_tables_priv_User test_columns_priv_User
+ok ok
+drop table test_columns_priv;
+drop table test_tables_priv;
+drop table test_func;
+drop table test_host;
+drop table test_user;
+drop table test_db;
diff --git a/mysql-test/r/true.require b/mysql-test/r/true.require
new file mode 100644
index 00000000000..09aae1ed1d0
--- /dev/null
+++ b/mysql-test/r/true.require
@@ -0,0 +1,2 @@
+TRUE
+1
diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result
index 0830179902d..68b56802120 100644
--- a/mysql-test/r/type_time.result
+++ b/mysql-test/r/type_time.result
@@ -25,9 +25,11 @@ t
36:30:31
insert into t1 values("10.22.22"),(1234567),(123456789),(123456789.10),("10 22:22"),("12.45a");
Warnings:
+Note 1292 Truncated wrong time value: '10.22.22'
Warning 1264 Data truncated, out of range for column 't' at row 2
Warning 1264 Data truncated, out of range for column 't' at row 3
Warning 1264 Data truncated, out of range for column 't' at row 4
+Note 1292 Truncated wrong time value: '12.45a'
select * from t1;
t
10:22:33
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index f89d41aa982..5eb447ab223 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -907,3 +907,18 @@ n
9
10
drop table t1;
+create table t1 (i int);
+insert into t1 values (1);
+select * from t1 UNION select * from t1;
+i
+1
+select * from t1 UNION ALL select * from t1;
+i
+1
+1
+select * from t1 UNION select * from t1 UNION ALL select * from t1;
+i
+1
+1
+1
+drop table t1;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index 5355e7ffadc..8934cd705b6 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -234,17 +234,17 @@ ERROR 42000: Unknown character set: 'UNKNOWN_CHARACTER_SET'
set collation_connection=UNKNOWN_COLLATION;
ERROR HY000: Unknown collation: 'UNKNOWN_COLLATION'
set global autocommit=1;
-ERROR HY000: Variable 'autocommit' is a LOCAL variable and can't be used with SET GLOBAL
+ERROR HY000: Variable 'autocommit' is a SESSION variable and can't be used with SET GLOBAL
select @@global.timestamp;
-ERROR HY000: Variable 'timestamp' is a LOCAL variable
+ERROR HY000: Variable 'timestamp' is a SESSION variable
set @@version='';
ERROR HY000: Unknown system variable 'version'
set @@concurrent_insert=1;
ERROR HY000: Variable 'concurrent_insert' is a GLOBAL variable and should be set with SET GLOBAL
set @@global.sql_auto_is_null=1;
-ERROR HY000: Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL
+ERROR HY000: Variable 'sql_auto_is_null' is a SESSION variable and can't be used with SET GLOBAL
select @@global.sql_auto_is_null;
-ERROR HY000: Variable 'sql_auto_is_null' is a LOCAL variable
+ERROR HY000: Variable 'sql_auto_is_null' is a SESSION variable
set myisam_max_sort_file_size=100;
ERROR HY000: 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;
@@ -382,6 +382,17 @@ select 1;
1
select @@session.key_buffer_size;
ERROR HY000: Variable 'key_buffer_size' is a GLOBAL variable
+set ft_boolean_syntax = @@init_connect;
+ERROR HY000: Variable 'ft_boolean_syntax' is a GLOBAL variable and should be set with SET GLOBAL
+set global ft_boolean_syntax = @@init_connect;
+ERROR 42000: Variable 'ft_boolean_syntax' can't be set to the value of ''
+set init_connect = NULL;
+ERROR HY000: Variable 'init_connect' is a GLOBAL variable and should be set with SET GLOBAL
+set global init_connect = NULL;
+set ft_boolean_syntax = @@init_connect;
+ERROR HY000: Variable 'ft_boolean_syntax' is a GLOBAL variable and should be set with SET GLOBAL
+set global ft_boolean_syntax = @@init_connect;
+ERROR 42000: Variable 'ft_boolean_syntax' can't be set to the value of ''
select @@global.max_user_connections,@@local.max_join_size;
@@global.max_user_connections @@session.max_join_size
100 200
@@ -406,3 +417,13 @@ set @a=@b, @b=@a;
select @a, @b;
@a @b
2 1
+set @@global.global.key_buffer_size= 1;
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size= 1' at line 1
+set GLOBAL global.key_buffer_size= 1;
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size= 1' at line 1
+SELECT @@global.global.key_buffer_size;
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
+SELECT @@global.session.key_buffer_size;
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
+SELECT @@global.local.key_buffer_size;
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 8da017e8acb..bb174c0225a 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -184,6 +184,17 @@ show create table t1;
drop table t1;
#
+# Bug#2821
+# Test that table CHARACTER SET does not affect blobs
+#
+create table t1 (myblob longblob,mytext longtext)
+default charset latin1 collate latin1_general_cs;
+show create table t1;
+alter table t1 character set latin2;
+show create table t1;
+drop table t1;
+
+#
# Test ALTER TABLE ENABLE/DISABLE keys when things are locked
#
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 70fa4173c76..253aa1bd8b9 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -220,6 +220,18 @@ select * from t1;
drop table t1;
#
+# Test for Bug #2985
+# "Table truncated when creating another table name with Spaces"
+#
+
+--error 1103
+create table `t1 `(a int);
+--error 1102
+create database `db1 `;
+--error 1166;
+create table t1(`a ` int);
+
+#
# Test create with foreign keys
#
@@ -347,6 +359,15 @@ describe t2;
drop table t1, t2;
#
+# test for bug #1427 "enum allows duplicate values in the list"
+#
+
+create table t1(cenum enum('a'), cset set('b'));
+create table t2(cenum enum('a','a'), cset set('b','b'));
+create table t3(cenum enum('a','A','a','c','c'), cset set('b','B','b','d','d'));
+drop table t1, t2, t3;
+
+#
# Bug #1209
#
@@ -359,3 +380,33 @@ select database();
# Connect without a database
connect (user4,localhost,mysqltest_1,,*NO-ONE*);
select database();
+
+#
+# Test for Bug 856 'Naming a key "Primary" causes trouble'
+#
+
+use test;
+--error 1280
+create table t1 (a int, index `primary` (a));
+--error 1280
+create table t1 (a int, index `PRIMARY` (a));
+
+create table t1 (`primary` int, index(`primary`));
+show create table t1;
+create table t2 (`PRIMARY` int, index(`PRIMARY`));
+show create table t2;
+
+create table t3 (a int);
+--error 1280
+alter table t3 add index `primary` (a);
+--error 1280
+alter table t3 add index `PRIMARY` (a);
+
+create table t4 (`primary` int);
+alter table t4 add index(`primary`);
+show create table t4;
+create table t5 (`PRIMARY` int);
+alter table t5 add index(`PRIMARY`);
+show create table t5;
+
+drop table t1, t2, t3, t4, t5;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 797af89c6ad..964ac84fbbe 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -54,7 +54,7 @@ select * from t1;
drop table t1;
#
-# Bug #2366 Wrong utf8 behaviour when data is trancated
+# Bug #2366 Wrong utf8 behaviour when data is truncated
#
set names koi8r;
create table t1 (s1 char(1) character set utf8);
@@ -101,7 +101,26 @@ drop table t1;
#
# Bug 2699
-# UTF8 breaks primary keys for cols > 85 characters
+# UTF8 breaks primary keys for cols > 333 characters
#
--error 1071
create table t1 (a text character set utf8, primary key(a(360)));
+
+
+#
+# Bug 2959
+# UTF8 charset breaks joins with mixed column/string constant
+#
+CREATE TABLE t1 ( a varchar(10) ) CHARACTER SET utf8;
+INSERT INTO t1 VALUES ( 'test' );
+SELECT a.a, b.a FROM t1 a, t1 b WHERE a.a = b.a;
+SELECT a.a, b.a FROM t1 a, t1 b WHERE a.a = 'test' and b.a = 'test';
+SELECT a.a, b.a FROM t1 a, t1 b WHERE a.a = b.a and a.a = 'test';
+DROP TABLE t1;
+
+create table t1 (a char(255) character set utf8);
+insert into t1 values('b'),('b');
+select * from t1 where a = 'b';
+select * from t1 where a = 'b' and a = 'b';
+select * from t1 where a = 'b' and a != 'b';
+drop table t1;
diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test
index 18af3dfb3db..1fc04cb907b 100644
--- a/mysql-test/t/date_formats.test
+++ b/mysql-test/t/date_formats.test
@@ -124,7 +124,7 @@ select str_to_date(concat('15-01-2001',' 2:59:58.999'),
create table t1 (date char(30), format char(30) not null);
insert into t1 values
('2003-01-02 10:11:12', '%Y-%m-%d %H:%i:%S'),
-('03-01-02 8:11:2.123456', '%y-%m-%d %H:%i:%S'),
+('03-01-02 8:11:2.123456', '%y-%m-%d %H:%i:%S.%#'),
('2003-01-02 10:11:12 PM', '%Y-%m-%d %h:%i:%S %p'),
('2003-01-02 01:11:12.12345AM', '%Y-%m-%d %h:%i:%S.%f%p'),
('2003-01-02 02:11:12.12345AM', '%Y-%m-%d %h:%i:%S.%f %p'),
@@ -209,3 +209,32 @@ create table t1 (d date);
insert into t1 values ('2004-07-14'),('2005-07-14');
select date_format(d,"%d") from t1 order by 1;
drop table t1;
+
+select str_to_date("2003-....01ABCD-02 10:11:12.0012", "%Y-%.%m%@-%d %H:%i:%S.%f") as a;
+
+
+create table t1 select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
+ str_to_date("10:11:12.0012", "%H:%i:%S.%f") as f2,
+ str_to_date("2003-01-02", "%Y-%m-%d") as f3,
+ str_to_date("02", "%d") as f4, str_to_date("02 10", "%d %H") as f5;
+describe t1;
+select * from t1;
+drop table t1;
+
+create table t1 select "02 10" as a, "%d %H" as b;
+select str_to_date(a,b) from t1;
+create table t2 select str_to_date(a,b) from t1;
+describe t2;
+select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
+ str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S") as f2,
+ str_to_date("2003-01-02", "%Y-%m-%d") as f3,
+ str_to_date("02 10:11:12", "%d %H:%i:%S.%f") as f4,
+ str_to_date("02 10:11:12", "%d %H:%i:%S") as f5,
+ str_to_date("02 10", "%d %f") as f6;
+drop table t1, t2;
+select str_to_date("2003-01-02 10:11:12.0012ABCD", "%Y-%m-%d %H:%i:%S.%f") as f1,
+ addtime("-01:01:01.01 GGG", "-23:59:59.1") as f2,
+ microsecond("1997-12-31 23:59:59.01XXXX") as f3;
+
+select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1,
+ str_to_date("2003-04-05 10:11:12.101010234567", "%Y-%m-%d %H:%i:%S.%f") as f2;
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 0ef56191b7c..f0d5a253bf4 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -157,7 +157,8 @@ UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1)
UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
select * from t1;
--- error 1288
+--replace_result P2 p2
+--error 1288
delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
-- error 1054
delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
@@ -188,7 +189,6 @@ INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00
select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
drop table t1, t2, t3;
-
#
# explain derived
#
@@ -206,3 +206,11 @@ insert into t2 values (1,7),(2,7);
explain select a from t2 where a>1;
explain select a from (select a from t2 where a>1) tt;
drop table t2;
+
+#
+# select list counter
+#
+CREATE TABLE `t1` ( `itemid` int(11) NOT NULL default '0', `grpid` varchar(15) NOT NULL default '', `vendor` int(11) NOT NULL default '0', `date_` date NOT NULL default '0000-00-00', `price` decimal(12,2) NOT NULL default '0.00', PRIMARY KEY (`itemid`,`grpid`,`vendor`,`date_`), KEY `itemid` (`itemid`,`vendor`), KEY `itemid_2` (`itemid`,`date_`));
+insert into t1 values (128, 'rozn', 2, now(), 10),(128, 'rozn', 1, now(), 10);
+SELECT MIN(price) min, MAX(price) max, AVG(price) avg FROM (SELECT SUBSTRING( MAX(concat(date_,";",price)), 12) price FROM t1 WHERE itemid=128 AND grpid='rozn' GROUP BY itemid, grpid, vendor) lastprices;
+DROP TABLE t1;
diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test
index 43329a849f8..88c47803f48 100644
--- a/mysql-test/t/drop.test
+++ b/mysql-test/t/drop.test
@@ -24,7 +24,9 @@ create database mysqltest;
create table mysqltest.mysqltest (n int);
insert into mysqltest.mysqltest values (4);
select * from mysqltest.mysqltest;
+--enable_info
drop database if exists mysqltest;
+--disable_info
create database mysqltest;
drop database mysqltest;
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index 1b56889aec7..50a3d522e3d 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -63,6 +63,9 @@ select * from t1 where MATCH a,b AGAINST ('"text search" "now support"' IN BOOL
select * from t1 where MATCH a,b AGAINST ('"text search" -"now support"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"text search" +"now support"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"text i"' IN BOOLEAN MODE);
+
+select * from t1 where MATCH a,b AGAINST ('+(support collections) +foobar*' IN BOOLEAN MODE);
+select * from t1 where MATCH a,b AGAINST ('+(+(support collections)) +foobar*' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE);
# bug#2708 crash
diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test
index e44a7f6d6f9..36c3a38d2fe 100644
--- a/mysql-test/t/func_if.test
+++ b/mysql-test/t/func_if.test
@@ -30,6 +30,12 @@ explain extended select nullif(u=0, 'test') from t1;
drop table t1;
#
+# Bug 2629
+#
+select NULLIF(NULL,NULL), NULLIF(NULL,1), NULLIF(NULL,1.0), NULLIF(NULL,"test");
+select NULLIF(1,NULL), NULLIF(1.0, NULL), NULLIF("test", NULL);
+
+#
# Problem with IF()
#
diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test
index 8b719b077f2..91f55af48cc 100644
--- a/mysql-test/t/func_like.test
+++ b/mysql-test/t/func_like.test
@@ -35,6 +35,14 @@ select * from t1 where a like 'a\\%' escape '#';
select * from t1 where a like 'a\\%' escape '#' and a like 'a\\\\b';
drop table t1;
+#
+# Bug #2885: like and datetime
+#
+
+create table t1 (a datetime);
+insert into t1 values ('2004-03-11 12:00:21');
+select * from t1 where a like '2004-03-11 12:00:21';
+drop table t1;
#
# Test like with non-default character set
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index 0f473abb96d..36ad2dfb0a2 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -40,4 +40,14 @@ SELECT ACOS(0.2*5.0);
SELECT ACOS(0.5*2.0);
SELECT ASIN(0.8+0.2);
SELECT ASIN(1.2-0.2);
+
+#
+# Bug #3051 FLOOR returns invalid
+#
+
+# This can't be tested as it's not portable
+#select floor(log(4)/log(2));
+#select floor(log(8)/log(2));
+#select floor(log(16)/log(2));
+
explain extended select degrees(pi()),radians(360);
diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test
index adc0a5a9263..e73f2a1b26c 100644
--- a/mysql-test/t/func_misc.test
+++ b/mysql-test/t/func_misc.test
@@ -12,6 +12,8 @@ select hex(inet_aton('127'));
select hex(inet_aton('127.1'));
select hex(inet_aton('127.1.1'));
+select length(uuid()), charset(uuid()), length(unhex(replace(uuid(),_utf8'-',_utf8'')));
+
#
# Test for core dump with nan
#
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
index afd84fe9630..24028437fde 100644
--- a/mysql-test/t/func_sapdb.test
+++ b/mysql-test/t/func_sapdb.test
@@ -97,3 +97,9 @@ SELECT ADDTIME(t1,t2) As ttt, ADDTIME(t2, t3) As qqq from test;
SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test;
drop table t1, test;
+
+select addtime("-01:01:01.01", "-23:59:59.1") as a;
+select microsecond("1997-12-31 23:59:59.01") as a;
+select microsecond(19971231235959.01) as a;
+select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a;
+select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f");
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index a9c2895206d..1c85f83baac 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -78,6 +78,9 @@ select quote(concat('abc\'', '\\cba'));
select quote(1/0), quote('\0\Z');
select length(quote(concat(char(0),"test")));
select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235))));
+select unhex(hex("foobar")), hex(unhex("1234567890ABCDEF")), unhex("345678");
+select hex(unhex("1")), hex(unhex("12")), hex(unhex("123")), hex(unhex("1234")), hex(unhex("12345")), hex(unhex("123456"));
+select length(unhex(md5("abrakadabra")));
#
# Wrong usage of functions
@@ -192,6 +195,8 @@ select concat(_latin1'a',_latin2'a');
select concat(_latin1'a',_latin2'a',_latin5'a');
--error 1271
select concat(_latin1'a',_latin2'a',_latin5'a',_latin7'a');
+--error 1267
+select concat_ws(_latin1'a',_latin2'a');
#
# Test FIELD() and collations
@@ -357,3 +362,23 @@ explain extended select md5('hello'), sha('abc'), sha1('abc'), soundex(''), 'moo
#
SELECT lpad(12345, 5, "#");
+
+#
+# Bug #2972
+#
+
+SELECT conv(71, 10, 36), conv('1Z', 36, 10);
+
+
+
+#
+# Bug #3089
+#
+
+create table t1 (id int(1), str varchar(10)) DEFAULT CHARSET=utf8;
+insert into t1 values (1,'aaaaaaaaaa'), (2,'bbbbbbbbbb');
+create table t2 (id int(1), str varchar(10)) DEFAULT CHARSET=utf8;
+insert into t2 values (1,'cccccccccc'), (2,'dddddddddd');
+select substring(concat(t1.str, t2.str), 1, 15) "name" from t1, t2
+where t2.id=t1.id order by name;
+drop table t1, t2;
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 06d0ff3fa1d..6417d5448e5 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -249,12 +249,18 @@ select last_day('2000-02-05') as f1, last_day('2002-12-31') as f2,
last_day('2001-01-01 01:01:01') as f5, last_day(NULL),
last_day('2001-02-12');
-create table t1 select last_day('2000-02-05') as a;
+create table t1 select last_day('2000-02-05') as a,
+ from_days(to_days("960101")) as b;
describe t1;
select * from t1;
drop table t1;
-select last_day('2000-02-05');
+select last_day('2000-02-05') as a,
+ from_days(to_days("960101")) as b;
+select date_add(last_day("1997-12-1"), INTERVAL 1 DAY);
+select length(last_day("1997-12-1"));
+select last_day("1997-12-1")+0;
+select last_day("1997-12-1")+0.0;
# Test SAPDB UTC_% functions. This part is TZ dependant (It is supposed that
# TZ variable set to GMT-3
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index c8f50e968ab..ea460d5f7b0 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -3,154 +3,155 @@
#
--disable_warnings
-DROP TABLE IF EXISTS pt, ls, p, mpt, mls, mp, gc, geo;
+DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
--enable_warnings
-CREATE TABLE pt (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
-CREATE TABLE ls (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
-CREATE TABLE p (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
-CREATE TABLE mpt (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
-CREATE TABLE mls (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
-CREATE TABLE mp (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
-CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
-CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
-
-SHOW FIELDS FROM pt;
-SHOW FIELDS FROM ls;
-SHOW FIELDS FROM p;
-SHOW FIELDS FROM mpt;
-SHOW FIELDS FROM mls;
-SHOW FIELDS FROM mp;
-SHOW FIELDS FROM gc;
-SHOW FIELDS FROM geo;
-
-
-INSERT INTO pt VALUES
+CREATE TABLE gis_point (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
+CREATE TABLE gis_line (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
+CREATE TABLE gis_polygon (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
+CREATE TABLE gis_multi_point (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
+CREATE TABLE gis_multi_line (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
+CREATE TABLE gis_multi_polygon (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
+CREATE TABLE gis_geometrycollection (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
+CREATE TABLE gis_geometry (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
+
+SHOW FIELDS FROM gis_point;
+SHOW FIELDS FROM gis_line;
+SHOW FIELDS FROM gis_polygon;
+SHOW FIELDS FROM gis_multi_point;
+SHOW FIELDS FROM gis_multi_line;
+SHOW FIELDS FROM gis_multi_polygon;
+SHOW FIELDS FROM gis_geometrycollection;
+SHOW FIELDS FROM gis_geometry;
+
+
+INSERT INTO gis_point VALUES
(101, PointFromText('POINT(10 10)')),
(102, PointFromText('POINT(20 10)')),
(103, PointFromText('POINT(20 20)')),
(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)'))));
-INSERT INTO ls VALUES
+INSERT INTO gis_line VALUES
(105, LineFromText('LINESTRING(0 0,0 10,10 0)')),
(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')),
(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10))));
-INSERT INTO p VALUES
+INSERT INTO gis_polygon VALUES
(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')),
(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')),
(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)))));
-INSERT INTO mpt VALUES
+INSERT INTO gis_multi_point VALUES
(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')),
(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')),
(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10))));
-INSERT INTO mls VALUES
+INSERT INTO gis_multi_line VALUES
(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')),
(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')),
(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7)))));
-INSERT INTO mp VALUES
+INSERT INTO gis_multi_polygon VALUES
(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3))))));
-INSERT INTO gc VALUES
+INSERT INTO gis_geometrycollection VALUES
(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')),
(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))));
-INSERT into geo SELECT * FROM pt;
-INSERT into geo SELECT * FROM ls;
-INSERT into geo SELECT * FROM p;
-INSERT into geo SELECT * FROM mpt;
-INSERT into geo SELECT * FROM mls;
-INSERT into geo SELECT * FROM mp;
-INSERT into geo SELECT * FROM gc;
-
-SELECT fid, AsText(g) FROM pt;
-SELECT fid, AsText(g) FROM ls;
-SELECT fid, AsText(g) FROM p;
-SELECT fid, AsText(g) FROM mpt;
-SELECT fid, AsText(g) FROM mls;
-SELECT fid, AsText(g) FROM mp;
-SELECT fid, AsText(g) FROM gc;
-SELECT fid, AsText(g) FROM geo;
-
-SELECT fid, Dimension(g) FROM geo;
-SELECT fid, GeometryType(g) FROM geo;
-SELECT fid, IsEmpty(g) FROM geo;
-SELECT fid, AsText(Envelope(g)) FROM geo;
-explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from geo;
-
-SELECT fid, X(g) FROM pt;
-SELECT fid, Y(g) FROM pt;
-explain extended select X(g),Y(g) FROM pt;
-
-SELECT fid, AsText(StartPoint(g)) FROM ls;
-SELECT fid, AsText(EndPoint(g)) FROM ls;
-SELECT fid, GLength(g) FROM ls;
-SELECT fid, NumPoints(g) FROM ls;
-SELECT fid, AsText(PointN(g, 2)) FROM ls;
-SELECT fid, IsClosed(g) FROM ls;
-explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM ls;
-
-SELECT fid, AsText(Centroid(g)) FROM p;
-SELECT fid, Area(g) FROM p;
-SELECT fid, AsText(ExteriorRing(g)) FROM p;
-SELECT fid, NumInteriorRings(g) FROM p;
-SELECT fid, AsText(InteriorRingN(g, 1)) FROM p;
-explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM p;
-
-SELECT fid, IsClosed(g) FROM mls;
-
-SELECT fid, AsText(Centroid(g)) FROM mp;
-SELECT fid, Area(g) FROM mp;
-
-SELECT fid, NumGeometries(g) from mpt;
-SELECT fid, NumGeometries(g) from mls;
-SELECT fid, NumGeometries(g) from mp;
-SELECT fid, NumGeometries(g) from gc;
-explain extended SELECT fid, NumGeometries(g) from mpt;
-
-SELECT fid, AsText(GeometryN(g, 2)) from mpt;
-SELECT fid, AsText(GeometryN(g, 2)) from mls;
-SELECT fid, AsText(GeometryN(g, 2)) from mp;
-SELECT fid, AsText(GeometryN(g, 2)) from gc;
-explain extended SELECT fid, AsText(GeometryN(g, 2)) from mpt;
+INSERT into gis_geometry SELECT * FROM gis_point;
+INSERT into gis_geometry SELECT * FROM gis_line;
+INSERT into gis_geometry SELECT * FROM gis_polygon;
+INSERT into gis_geometry SELECT * FROM gis_multi_point;
+INSERT into gis_geometry SELECT * FROM gis_multi_line;
+INSERT into gis_geometry SELECT * FROM gis_multi_polygon;
+INSERT into gis_geometry SELECT * FROM gis_geometrycollection;
+
+SELECT fid, AsText(g) FROM gis_point;
+SELECT fid, AsText(g) FROM gis_line;
+SELECT fid, AsText(g) FROM gis_polygon;
+SELECT fid, AsText(g) FROM gis_multi_point;
+SELECT fid, AsText(g) FROM gis_multi_line;
+SELECT fid, AsText(g) FROM gis_multi_polygon;
+SELECT fid, AsText(g) FROM gis_geometrycollection;
+SELECT fid, AsText(g) FROM gis_geometry;
+
+SELECT fid, Dimension(g) FROM gis_geometry;
+SELECT fid, GeometryType(g) FROM gis_geometry;
+SELECT fid, IsEmpty(g) FROM gis_geometry;
+SELECT fid, AsText(Envelope(g)) FROM gis_geometry;
+explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry;
+
+SELECT fid, X(g) FROM gis_point;
+SELECT fid, Y(g) FROM gis_point;
+explain extended select X(g),Y(g) FROM gis_point;
+
+SELECT fid, AsText(StartPoint(g)) FROM gis_line;
+SELECT fid, AsText(EndPoint(g)) FROM gis_line;
+SELECT fid, GLength(g) FROM gis_line;
+SELECT fid, NumPoints(g) FROM gis_line;
+SELECT fid, AsText(PointN(g, 2)) FROM gis_line;
+SELECT fid, IsClosed(g) FROM gis_line;
+explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line;
+
+SELECT fid, AsText(Centroid(g)) FROM gis_polygon;
+SELECT fid, Area(g) FROM gis_polygon;
+SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon;
+SELECT fid, NumInteriorRings(g) FROM gis_polygon;
+SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon;
+explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon;
+
+SELECT fid, IsClosed(g) FROM gis_multi_line;
+
+SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
+SELECT fid, Area(g) FROM gis_multi_polygon;
+
+SELECT fid, NumGeometries(g) from gis_multi_point;
+SELECT fid, NumGeometries(g) from gis_multi_line;
+SELECT fid, NumGeometries(g) from gis_multi_polygon;
+SELECT fid, NumGeometries(g) from gis_geometrycollection;
+explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
+
+SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
+SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line;
+SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon;
+SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection;
+SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection;
+explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
-FROM gc g1, gc g2 ORDER BY first, second;
+FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
-FROM gc g1, gc g2 ORDER BY first, second;
+FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
-DROP TABLE pt, ls, p, mpt, mls, mp, gc, geo;
+DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
#
# Check that ALTER TABLE doesn't loose geometry type
#
-CREATE TABLE g1 (
- pt point,
+CREATE TABLE t1 (
+ gp point,
ln linestring,
pg polygon,
- mpt multipoint,
+ mp multipoint,
mln multilinestring,
mpg multipolygon,
gc geometrycollection,
gm geometry
);
-SHOW FIELDS FROM g1;
-ALTER TABLE g1 ADD fid INT NOT NULL;
-SHOW FIELDS FROM g1;
-DROP TABLE g1;
+SHOW FIELDS FROM t1;
+ALTER TABLE t1 ADD fid INT NOT NULL;
+SHOW FIELDS FROM t1;
+DROP TABLE t1;
SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))));
explain extended SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))));
@@ -159,3 +160,13 @@ SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
explain extended SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
#select issimple(MultiPoint(Point(3, 6), Point(4, 10))), issimple(Point(3, 6)),issimple(PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')),issimple(GeometryFromText('POINT(1 4)')), issimple(AsWKB(GeometryFromText('POINT(1 4)')));
explain extended select issimple(MultiPoint(Point(3, 6), Point(4, 10))), issimple(Point(3, 6));
+
+create table t1 (a geometry not null);
+insert into t1 values (GeomFromText('Point(1 2)'));
+-- error 1105
+insert into t1 values ('Garbage');
+-- error 1105
+insert IGNORE into t1 values ('Garbage');
+alter table t1 add spatial index(a);
+
+drop table t1;
diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test
index e6b19e86c90..326759cb9ca 100644
--- a/mysql-test/t/grant.test
+++ b/mysql-test/t/grant.test
@@ -107,6 +107,23 @@ grant ALL PRIVILEGES on *.* to drop_user@localhost with GRANT OPTION;
grant ALL PRIVILEGES on test.* to drop_user@localhost with GRANT OPTION;
grant select(a) on test.t1 to drop_user@localhost;
show grants for drop_user@localhost;
+
+#
+# Bug3086
+#
+set sql_mode=ansi_quotes;
+show grants for drop_user@localhost;
+set sql_mode=default;
+
+set sql_quote_show_create=0;
+show grants for drop_user@localhost;
+set sql_mode="ansi_quotes";
+show grants for drop_user@localhost;
+set sql_quote_show_create=1;
+show grants for drop_user@localhost;
+set sql_mode="";
+show grants for drop_user@localhost;
+
revoke all privileges, grant option from drop_user@localhost;
show grants for drop_user@localhost;
drop user drop_user@localhost;
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index 73b5f453bb4..fd728c453aa 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -87,3 +87,56 @@ use mysqltest;
create table t1 (c int);
insert into mysqltest.t1 set mysqltest.t1.c = '1';
drop database mysqltest;
+
+#
+# Test of wrong values for float data (bug #2082)
+#
+
+use test;
+create table t1(number int auto_increment primary key, original_value varchar(50), f_double double, f_float float, f_double_7_2 double(7,2), f_float_4_3 float (4,3), f_double_u double unsigned, f_float_u float unsigned, f_double_15_1_u double(15,1) unsigned, f_float_3_1_u float (3,1) unsigned);
+
+set @value= "aa";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= "1aa";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= "aa1";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= "1e+1111111111a";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= "-1e+1111111111a";
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= 1e+1111111111;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= -1e+1111111111;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= 1e+111;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= -1e+111;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= 1;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+set @value= -1;
+insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--query_vertical select * from t1 where number =last_insert_id()
+
+drop table t1;
diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test
index 550bce867cd..d2a70208022 100644
--- a/mysql-test/t/insert_update.test
+++ b/mysql-test/t/insert_update.test
@@ -26,3 +26,25 @@ SELECT *, VALUES(a) FROM t1;
explain extended SELECT *, VALUES(a) FROM t1;
explain extended select * from t1 where values(a);
DROP TABLE t1;
+
+#
+# test for Bug #2709 "Affected Rows for ON DUPL.KEY undocumented,
+# perhaps illogical"
+#
+create table t1(a int primary key, b int);
+insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5);
+select * from t1;
+
+enable_info;
+insert into t1 values(4,14),(5,15),(6,16),(7,17),(8,18)
+ on duplicate key update b=b+10;
+disable_info;
+
+select * from t1;
+
+enable_info;
+replace into t1 values(5,25),(6,26),(7,27),(8,28),(9,29);
+disable_info;
+
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test
index 601f1734ac6..db46f3d432d 100644
--- a/mysql-test/t/lowercase_table.test
+++ b/mysql-test/t/lowercase_table.test
@@ -3,7 +3,7 @@
#
--disable_warnings
-drop table if exists t1,t2,t3,t4,T1;
+drop table if exists t1,t2,t3,t4;
--enable_warnings
create table T1 (id int primary key, Word varchar(40) not null, Index(Word));
@@ -30,3 +30,27 @@ select count(*) from t1;
select count(T1.a) from t1;
select count(bags.a) from t1 as Bags;
drop table t1;
+
+#
+# multiupdate/delete & --lower-case-table-names
+#
+create table t1 (a int);
+create table t2 (a int);
+delete p1.*,P2.* from t1 as p1, t2 as p2 where p1.a=P2.a;
+delete P1.*,p2.* from t1 as P1, t2 as P2 where P1.a=p2.a;
+update t1 as p1, t2 as p2 SET p1.a=1,P2.a=1 where p1.a=P2.a;
+update t1 as P1, t2 as P2 SET P1.a=1,p2.a=1 where P1.a=p2.a;
+drop table t1,t2;
+
+#
+# aliases case insensitive
+#
+create table t1 (a int);
+create table t2 (a int);
+-- error 1066
+select * from t1 c, t2 C;
+-- error 1066
+select C.a, c.a from t1 c, t2 C;
+drop table t1, t2;
+
+show tables;
diff --git a/mysql-test/t/lowercase_table2.test b/mysql-test/t/lowercase_table2.test
index 86bb26f0cf9..8f542a7af78 100644
--- a/mysql-test/t/lowercase_table2.test
+++ b/mysql-test/t/lowercase_table2.test
@@ -78,3 +78,14 @@ RENAME TABLE T2 TO T1;
SHOW TABLES LIKE "T1";
SELECT * from T1;
DROP TABLE T1;
+
+#
+# Test problem with temporary tables (Bug #2858)
+#
+
+create table T1 (EVENT_ID int auto_increment primary key, LOCATION char(20));
+insert into T1 values (NULL,"Mic-4"),(NULL,"Mic-5"),(NULL,"Mic-6");
+SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
+SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
+SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
+drop table T1;
diff --git a/mysql-test/t/lowercase_table2-master.opt b/mysql-test/t/lowercase_table3-master.opt
index 9b27aef9bf8..9b27aef9bf8 100644
--- a/mysql-test/t/lowercase_table2-master.opt
+++ b/mysql-test/t/lowercase_table3-master.opt
diff --git a/mysql-test/t/lowercase_table3.test b/mysql-test/t/lowercase_table3.test
new file mode 100644
index 00000000000..735a0b390f9
--- /dev/null
+++ b/mysql-test/t/lowercase_table3.test
@@ -0,0 +1,37 @@
+#
+# Test of force of lower-case-table-names=0
+# (User has case insensitive file system and want's to preserve case of
+# table names)
+#
+
+--source include/have_innodb.inc
+--require r/lowercase0.require
+disable_query_log;
+show variables like "lower_case_%";
+--require r/true.require
+select @@version_compile_os NOT IN ("NT","WIN2000","Win95/Win98","XP") as "TRUE";
+enable_query_log;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1,T1;
+--enable_warnings
+
+#
+# This is actually an error, but ok as the user has forced this
+# by using --lower-case-table-names=0
+
+CREATE TABLE t1 (a int);
+SELECT * from T1;
+drop table t1;
+flush tables;
+
+#
+# InnoDB should in this case be case sensitive
+# Note that this is not true on windows as no this OS, InnoDB is always
+# storing things in lower case.
+#
+
+CREATE TABLE t1 (a int) type=INNODB;
+--error 1016
+SELECT * from T1;
+drop table t1;
diff --git a/mysql-test/t/lowercase_table_qcache-master.opt b/mysql-test/t/lowercase_table_qcache-master.opt
new file mode 100644
index 00000000000..c718e2feb1b
--- /dev/null
+++ b/mysql-test/t/lowercase_table_qcache-master.opt
@@ -0,0 +1 @@
+--lower_case_table_names
diff --git a/mysql-test/t/lowercase_table_qcache.test b/mysql-test/t/lowercase_table_qcache.test
new file mode 100644
index 00000000000..7416de25e1d
--- /dev/null
+++ b/mysql-test/t/lowercase_table_qcache.test
@@ -0,0 +1,29 @@
+-- source include/have_query_cache.inc
+#
+# Test of query cache with --lower-case-table-names
+#
+set GLOBAL query_cache_size=1355776;
+
+--disable_warnings
+drop database if exists MySQLtesT;
+--enable_warnings
+
+create database MySQLtesT;
+create table MySQLtesT.t1 (a int);
+select * from MySQLtesT.t1;
+show status like "Qcache_queries_in_cache";
+drop database mysqltest;
+show status like "Qcache_queries_in_cache";
+
+use MySQL;
+disable_result_log;
+select * from db;
+enable_result_log;
+show status like "Qcache_queries_in_cache";
+use test;
+disable_result_log;
+select * from MySQL.db;
+enable_result_log;
+show status like "Qcache_queries_in_cache";
+
+set GLOBAL query_cache_size=0; \ No newline at end of file
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index eb77734300f..27fd80e781b 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -344,3 +344,38 @@ select 't2 rows after big delete', count(*) from t2;
select 't1 rows after big delete', count(*) from t1;
drop table t1,t2;
+
+#
+# Test alias (this is not correct in 4.0)
+#
+
+CREATE TABLE t1 ( a int );
+CREATE TABLE t2 ( a int );
+DELETE t1 FROM t1, t2 AS t3;
+DELETE t4 FROM t1, t1 AS t4;
+DELETE t3 FROM t1 AS t3, t1 AS t4;
+--error 1066
+DELETE t1 FROM t1 AS t3, t2 AS t4;
+INSERT INTO t1 values (1),(2);
+INSERT INTO t2 values (1),(2);
+DELETE t1 FROM t1 AS t2, t2 AS t1 where t1.a=t2.a and t1.a=1;
+SELECT * from t1;
+SELECT * from t2;
+DELETE t2 FROM t1 AS t2, t2 AS t1 where t1.a=t2.a and t1.a=2;
+SELECT * from t1;
+SELECT * from t2;
+DROP TABLE t1,t2;
+
+#
+# Test update with const tables
+#
+
+create table `t1` (`p_id` int(10) unsigned NOT NULL auto_increment, `p_code` varchar(20) NOT NULL default '', `p_active` tinyint(1) unsigned NOT NULL default '1', PRIMARY KEY (`p_id`) );
+create table `t2` (`c2_id` int(10) unsigned NULL auto_increment, `c2_p_id` int(10) unsigned NOT NULL default '0', `c2_note` text NOT NULL, `c2_active` tinyint(1) unsigned NOT NULL default '1', PRIMARY KEY (`c2_id`), KEY `c2_p_id` (`c2_p_id`) );
+insert into t1 values (0,'A01-Comp',1);
+insert into t1 values (0,'B01-Comp',1);
+insert into t2 values (0,1,'A Note',1);
+update t1 left join t2 on p_id = c2_p_id set c2_note = 'asdf-1' where p_id = 2;
+select * from t1;
+select * from t2;
+drop table t1, t2;
diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
index 07adf2732dc..1b07ddc63a6 100644
--- a/mysql-test/t/mysqlbinlog.test
+++ b/mysql-test/t/mysqlbinlog.test
@@ -70,7 +70,6 @@ select "--- Remote --" as "";
--enable_query_log
# This is broken now
-# By the way it seems that remote version fetches all events with name >= master-bin.000001
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 3e9f67b0ab1..28992655bd2 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -73,6 +73,19 @@ create table ```a` (i int);
drop table ```a`;
#
+# Bug #2591 "mysqldump quotes names inconsistently"
+#
+
+create table t1(a int);
+--exec $MYSQL_DUMP --comments=0 test
+--exec $MYSQL_DUMP --comments=0 --compatible=ansi test
+set global sql_mode='ANSI_QUOTES';
+--exec $MYSQL_DUMP --comments=0 test
+--exec $MYSQL_DUMP --comments=0 --compatible=ansi test
+set global sql_mode='';
+drop table t1;
+
+#
# Bug #2705 'mysqldump --tab extra output'
#
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index bbb0046b47f..2cd8dbbb95a 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -393,3 +393,28 @@ select * from t1 where b=1 or b is null order by a;
explain select * from t1 where b=2 or b is null order by a;
select * from t1 where b=2 or b is null order by a;
drop table t1;
+
+#
+# Bug #3155
+#
+
+create table t1 (a int not null auto_increment, b int not null, c int not null, d int not null,
+key(a,b,d), key(c,b,a));
+create table t2 like t1;
+insert into t1 values (NULL, 1, 2, 0), (NULL, 2, 1, 1), (NULL, 3, 4, 2), (NULL, 4, 3, 3);
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+optimize table t1;
+set @row=10;
+insert into t1 select 1, b, c + (@row:=@row - 1) * 10, d - @row from t2 limit 10;
+select * from t1 where a=1 and b in (1) order by c, b, a;
+select * from t1 where a=1 and b in (1);
+drop table t1, t2;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 5ae2039138d..31aa69e32ec 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -544,10 +544,25 @@ select * from t3;
enable_result_log;
delete from t4 where a=1;
flush query cache;
-
drop table t1,t2,t3,t4;
#
+# WRITE LOCK & QC
+#
+set query_cache_wlock_invalidate=1;
+create table t1 (a int not null);
+create table t2 (a int not null);
+select * from t1;
+select * from t2;
+show status like "Qcache_queries_in_cache";
+lock table t1 write, t2 read;
+show status like "Qcache_queries_in_cache";
+unlock table;
+drop table t1,t2;
+set query_cache_wlock_invalidate=default;
+
+
+#
# Test character set related variables:
# character_set_result
# character_set_client
diff --git a/mysql-test/t/rpl000009.test b/mysql-test/t/rpl000009.test
index cd318efa2b6..59451bc888d 100644
--- a/mysql-test/t/rpl000009.test
+++ b/mysql-test/t/rpl000009.test
@@ -118,6 +118,21 @@ connection slave;
sync_with_master;
select * from mysqltest.t1;
+# Check that LOAD DATA FROM MASTER is able to create master.info
+# if needed (if RESET SLAVE was used before), before writing to it (BUG#2922).
+
+stop slave;
+reset slave;
+load data from master;
+start slave;
+# see if replication coordinates were restored fine
+connection master;
+insert into mysqltest.t1 values (5, 'five bar');
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from mysqltest.t1;
+
# Check that LOAD DATA FROM MASTER reports the error if it can't drop a
# table to be overwritten.
# DISABLED FOR NOW AS chmod IS NOT PORTABLE ON NON-UNIX
diff --git a/mysql-test/t/rpl_error_ignored_table-slave.opt b/mysql-test/t/rpl_error_ignored_table-slave.opt
index 0d3485f9e25..cb49119bfcb 100644
--- a/mysql-test/t/rpl_error_ignored_table-slave.opt
+++ b/mysql-test/t/rpl_error_ignored_table-slave.opt
@@ -1 +1 @@
---replicate-ignore-table=test.t1
+--replicate-ignore-table=test.t1 --replicate-ignore-table=test.t2 --replicate-ignore-table=test.t3
diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test
index aacdb506107..40dbe455c7a 100644
--- a/mysql-test/t/rpl_error_ignored_table.test
+++ b/mysql-test/t/rpl_error_ignored_table.test
@@ -24,3 +24,33 @@ drop table t1;
save_master_pos;
connection slave;
sync_with_master;
+
+# Now test that even critical errors (connection killed)
+# are ignored if rules allow it.
+# The "kill" idea was copied from rpl000001.test.
+
+connection master1;
+select get_lock('crash_lock%20C', 10);
+
+connection master;
+create table t2 (a int primary key);
+insert into t2 values(1);
+create table t3 (id int);
+insert into t3 values(connection_id());
+send update t2 set a = a + 1 + get_lock('crash_lock%20C', 10);
+
+connection master1;
+sleep 2;
+select (@id := id) - id from t3;
+kill @id;
+drop table t2,t3;
+connection master;
+--error 1053,0;
+reap;
+connection master1;
+show binlog events from 79;
+save_master_pos;
+connection slave;
+# SQL slave thread should not have stopped (because table of the killed
+# query is in the ignore list).
+sync_with_master;
diff --git a/mysql-test/t/rpl_optimize.test b/mysql-test/t/rpl_optimize.test
new file mode 100644
index 00000000000..9f02b715885
--- /dev/null
+++ b/mysql-test/t/rpl_optimize.test
@@ -0,0 +1,43 @@
+# Test for BUG#1858 "OPTIMIZE TABLE done by a client
+# thread stops the slave SQL thread".
+# You can replace OPTIMIZE by REPAIR.
+
+source include/master-slave.inc;
+
+create table t1 (a int not null auto_increment primary key, b int, key(b));
+INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+INSERT INTO t1 (a) SELECT null FROM t1;
+save_master_pos;
+# a few updates to force OPTIMIZE to do something
+update t1 set b=(a/2*rand());
+delete from t1 order by b limit 10000;
+
+connection slave;
+sync_with_master;
+optimize table t1;
+connection master;
+save_master_pos;
+connection slave;
+# Bug was that when the INSERT terminated on slave,
+# the slave SQL thread got killed by OPTIMIZE.
+sync_with_master; # won't work if slave SQL thread stopped
+
+connection master; # cleanup
+drop table t1;
+connection slave;
+sync_with_master;
+
+# If the machine is so fast that slave syncs before OPTIMIZE
+# starts, this test wil demonstrate nothing but will pass.
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index 935e472c4a1..638626a7456 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -54,8 +54,8 @@ create table t1 (
test_set set( 'val1', 'val2', 'val3' ) not null default '',
name char(20) default 'O''Brien' comment 'O''Brien as default',
c int not null comment 'int column',
- `c-b` int comment 'name with a space',
- `space ` int comment 'name with a space',
+ `c-b` int comment 'name with a minus',
+ `space 2` int comment 'name with a space',
) comment = 'it\'s a table' ;
show create table t1;
set sql_quote_show_create=0;
@@ -147,31 +147,43 @@ drop table t1;
# Test for Bug #2593 "SHOW CREATE TABLE doesn't properly double quotes"
#
-SET sql_mode='';
-SET sql_quote_show_create=OFF;
-
-CREATE TABLE ```ab``cd``` (i INT);
-SHOW CREATE TABLE ```ab``cd```;
-DROP TABLE ```ab``cd```;
-
-CREATE TABLE ```ab````cd``` (i INT);
-SHOW CREATE TABLE ```ab````cd```;
-DROP TABLE ```ab````cd```;
-
-CREATE TABLE ```a` (i INT);
-SHOW CREATE TABLE ```a`;
-DROP TABLE ```a`;
-
-SET sql_mode='ANSI_QUOTES';
-
-CREATE TABLE """a" (i INT);
-SHOW CREATE TABLE """a";
-DROP TABLE """a";
+SET @old_sql_mode= @@sql_mode, sql_mode= '';
+SET @old_sql_quote_show_create= @@sql_quote_show_create, sql_quote_show_create= OFF;
+
+######### hook for WL#1324 #
+--error 1103
+CREATE TABLE `a/b` (i INT);
+# the above test should WORK when WL#1324 is done,
+# it should be removed and
+# the following part should be uncommented then
+#########################################################
+# begin of part that must be uncommented when WL#1324 is done
+#########################################################
+#CREATE TABLE ```ab``cd``` (i INT);
+#SHOW CREATE TABLE ```ab``cd```;
+#DROP TABLE ```ab``cd```;
+
+#CREATE TABLE ```ab````cd``` (i INT);
+#SHOW CREATE TABLE ```ab````cd```;
+#DROP TABLE ```ab````cd```;
+
+#CREATE TABLE ```a` (i INT);
+#SHOW CREATE TABLE ```a`;
+#DROP TABLE ```a`;
+
+SET sql_mode= 'ANSI_QUOTES';
+
+#CREATE TABLE """a" (i INT);
+#SHOW CREATE TABLE """a";
+#DROP TABLE """a";
+#########################################################
+# end of part that must be uncommented when WL#1324 is done
+#########################################################
# to test quotes around keywords.. :
-SET sql_mode='';
-SET sql_quote_show_create=OFF;
+SET sql_mode= '';
+SET sql_quote_show_create= OFF;
CREATE TABLE t1 (i INT);
SHOW CREATE TABLE t1;
@@ -181,7 +193,8 @@ CREATE TABLE `table` (i INT);
SHOW CREATE TABLE `table`;
DROP TABLE `table`;
-SET sql_quote_show_create=ON;
+SET sql_quote_show_create= @old_sql_quote_show_create;
+SET sql_mode= @old_sql_mode;
#
# Test for bug #2719 "Heap tables status shows wrong or missing data."
@@ -209,30 +222,37 @@ CREATE TABLE t3 (
insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1,1),(2,2);
+--replace_column 6 # 7 # 8 #
show table status;
insert into t1 values (3),(4);
insert into t2 values (3),(4);
insert into t3 values (3,3),(4,4);
+--replace_column 6 # 7 # 8 #
show table status;
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
+--replace_column 6 # 7 # 8 #
show table status;
delete from t1 where a=3;
delete from t2 where b=3;
delete from t3 where a=3;
+--replace_column 6 # 7 # 8 #
show table status;
delete from t1;
delete from t2;
delete from t3;
+--replace_column 6 # 7 # 8 #
show table status;
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
+--replace_column 6 # 7 # 8 #
show table status;
delete from t1 where a=5;
delete from t2 where b=5;
delete from t3 where a=5;
+--replace_column 6 # 7 # 8 #
show table status;
drop table t1, t2, t3;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 42fb2afbe89..8da67f84c86 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1010,6 +1010,11 @@ INSERT INTO t2 VALUES (100, 200, 'C');
SELECT DISTINCT COLC FROM t1 WHERE COLA = (SELECT COLA FROM t2 WHERE COLB = 200 AND COLC ='C' LIMIT 1);
DROP TABLE t1, t2;
+CREATE TABLE t1 (a int(1));
+INSERT INTO t1 VALUES (1),(1),(1),(1),(1),(2),(3),(4),(5);
+SELECT DISTINCT (SELECT a) FROM t1 LIMIT 100;
+DROP TABLE t1;
+
#
# Bug 2198
#
@@ -1060,3 +1065,43 @@ select sum(a) from (select * from t1) as a;
select 2 in (select * from t1);
SET SQL_SELECT_LIMIT=default;
drop table t1;
+
+#
+# Bug #3118: subselect + order by
+#
+
+CREATE TABLE t1 (a int, b int, INDEX (a));
+INSERT INTO t1 VALUES (1, 1), (1, 2), (1, 3);
+SELECT * FROM t1 WHERE a = (SELECT MAX(a) FROM t1 WHERE a = 1) ORDER BY b;
+DROP TABLE t1;
+
+# Item_cond fix field
+#
+create table t1(val varchar(10));
+insert into t1 values ('aaa'), ('bbb'),('eee'),('mmm'),('ppp');
+select count(*) from t1 as w1 where w1.val in (select w2.val from t1 as w2 where w2.val like 'm%') and w1.val in (select w3.val from t1 as w3 where w3.val like 'e%');
+drop table t1;
+
+#
+# ref_or_null replacing with ref
+#
+create table t1 (id int not null, text varchar(20) not null default '', primary key (id));
+insert into t1 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text11'), (12, 'text12');
+select * from t1 where id not in (select id from t1 where id < 8);
+select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
+explain extended select * from t1 where id not in (select id from t1 where id < 8);
+explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
+insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
+create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
+insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
+select * from t1 a left join t2 b on (a.id=b.id or b.id is null) join t1 c on (if(isnull(b.id), 1000, b.id)=c.id);
+explain extended select * from t1 a left join t2 b on (a.id=b.id or b.id is null) join t1 c on (if(isnull(b.id), 1000, b.id)=c.id);
+drop table t1,t2;
+
+#
+# Static tables & rund() in subqueries
+#
+create table t1 (a int);
+insert into t1 values (1);
+explain select benchmark(1000, (select a from t1 where a=sha(rand())));
+drop table t1;
diff --git a/mysql-test/t/system_mysql_db.test b/mysql-test/t/system_mysql_db.test
new file mode 100644
index 00000000000..bd69297b739
--- /dev/null
+++ b/mysql-test/t/system_mysql_db.test
@@ -0,0 +1,8 @@
+#
+# This test must examine integrity of system database "mysql"
+#
+
+-- disable_query_log
+use mysql;
+-- enable_query_log
+-- source include/system_db_struct.inc
diff --git a/mysql-test/t/system_mysql_db_fix-master.opt b/mysql-test/t/system_mysql_db_fix-master.opt
new file mode 100644
index 00000000000..69eb9d2cbf0
--- /dev/null
+++ b/mysql-test/t/system_mysql_db_fix-master.opt
@@ -0,0 +1 @@
+--result-file=system_mysql_db \ No newline at end of file
diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test
new file mode 100644
index 00000000000..6f3979bf66e
--- /dev/null
+++ b/mysql-test/t/system_mysql_db_fix.test
@@ -0,0 +1,78 @@
+#
+# This is the test for mysql_fix_privilege_tables
+#
+
+-- disable_result_log
+-- disable_query_log
+
+use test;
+
+# create system tables as in mysql-3.20
+
+CREATE TABLE db (
+ Host char(60) binary DEFAULT '' NOT NULL,
+ Db char(32) binary DEFAULT '' NOT NULL,
+ User char(16) binary DEFAULT '' NOT NULL,
+ Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ PRIMARY KEY Host (Host,Db,User),
+ KEY User (User)
+)
+type=ISAM;
+
+INSERT INTO db VALUES ('%','test', '','Y','Y','Y','Y','Y','Y');
+INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y');
+
+CREATE TABLE host (
+ Host char(60) binary DEFAULT '' NOT NULL,
+ Db char(32) binary DEFAULT '' NOT NULL,
+ Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ PRIMARY KEY Host (Host,Db)
+)
+type=ISAM;
+
+CREATE TABLE user (
+ Host char(60) binary DEFAULT '' NOT NULL,
+ User char(16) binary DEFAULT '' NOT NULL,
+ Password char(16),
+ Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ Process_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ PRIMARY KEY Host (Host,User)
+)
+type=ISAM;
+
+INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y');
+INSERT INTO user VALUES ('localhost','', '','N','N','N','N','N','N','N','N','N');
+
+-- exec $MYSQL_FIX_SYSTEM_TABLES --database=test
+-- enable_query_log
+-- enable_result_log
+
+-- source include/system_db_struct.inc
+
+-- disable_query_log
+
+DROP TABLE db;
+DROP TABLE host;
+DROP TABLE user;
+DROP TABLE func;
+DROP TABLE tables_priv;
+DROP TABLE columns_priv;
+
+-- enable_query_log
diff --git a/mysql-test/t/system_mysql_db_refs.test b/mysql-test/t/system_mysql_db_refs.test
new file mode 100644
index 00000000000..62d6f3de944
--- /dev/null
+++ b/mysql-test/t/system_mysql_db_refs.test
@@ -0,0 +1,101 @@
+#
+# This test must examine integrity of current system database
+#
+
+set @name="This is a very long string, that mustn't find room in a system field like Table_name. Thus it should be cut by the actual size of the field. So we can use this string to find out the actual length of the field and to use it in any compare queries";
+
+#
+# If this part is wrong, most likely you've done wrong modification of system database "mysql"
+#
+
+create table test_db select * from mysql.db;
+delete from test_db;
+--disable_warnings
+insert into test_db (Host,Db,User) values (@name,@name,@name);
+--enable_warnings
+
+create table test_host select * from mysql.host;
+delete from test_host;
+--disable_warnings
+insert into test_host (Host,Db) values (@name,@name);
+--enable_warnings
+
+create table test_user select * from mysql.user;
+delete from test_user;
+--disable_warnings
+insert into test_user (Host,User) values (@name,@name);
+--enable_warnings
+
+create table test_func select * from mysql.func;
+delete from test_func;
+--disable_warnings
+insert into test_func (name) values (@name);
+--enable_warnings
+
+create table test_tables_priv select * from mysql.tables_priv;
+delete from test_tables_priv;
+--disable_warnings
+insert into test_tables_priv (Host,Db,User,Table_name) values (@name,@name,@name,@name);
+--enable_warnings
+
+create table test_columns_priv select * from mysql.columns_priv;
+delete from test_columns_priv;
+--disable_warnings
+insert into test_columns_priv (Host,Db,User,Table_name,Column_name) values (@name,@name,@name,@name,@name);
+--enable_warnings
+
+# 'Host' field must be the same for all the tables:
+
+select
+ if(isnull(test_db.Host),'WRONG!!!','ok') as test_db_Host,
+ if(isnull(test_host.Host),'WRONG!!!','ok') as test_host_Host,
+ if(isnull(test_user.Host),'WRONG!!!','ok') as test_user_Host,
+ if(isnull(test_tables_priv.Host),'WRONG!!!','ok') as test_tables_priv_Host,
+ if(isnull(test_columns_priv.Host),'WRONG!!!','ok') as test_columns_priv_Host
+
+from test_db
+left join test_host on test_db.Host=test_host.Host
+left join test_user on test_db.Host=test_user.Host
+left join test_tables_priv on test_db.Host=test_tables_priv.Host
+left join test_columns_priv on test_db.Host=test_columns_priv.Host;
+
+# 'Db' field must be the same for all the tables:
+
+select
+ if(isnull(test_db.Db),'WRONG!!!','ok') as test_db_Db,
+ if(isnull(test_host.Db),'WRONG!!!','ok') as test_host_Db,
+ if(isnull(test_tables_priv.Db),'WRONG!!!','ok') as test_tables_priv_Db,
+ if(isnull(test_columns_priv.Db),'WRONG!!!','ok') as est_columns_priv_Db
+
+from test_db
+left join test_host on test_db.Db=test_host.Db
+left join test_tables_priv on test_db.Db=test_tables_priv.Db
+left join test_columns_priv on test_db.Db=test_columns_priv.Db;
+
+# 'User' field must be the same for all the tables:
+
+select
+ if(isnull(test_db.User),'WRONG!!!','ok') as test_db_User,
+ if(isnull(test_user.User),'WRONG!!!','ok') as test_user_User,
+ if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User,
+ if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User
+
+from test_db
+left join test_user on test_db.User=test_user.User
+left join test_tables_priv on test_db.User=test_tables_priv.User
+left join test_columns_priv on test_db.User=test_columns_priv.User;
+
+# 'Table_name' field must be the same for all the tables:
+
+select
+ if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User,
+ if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User
+from test_tables_priv
+left join test_columns_priv on test_tables_priv.Table_name=test_columns_priv.Table_name;
+
+drop table test_columns_priv;
+drop table test_tables_priv;
+drop table test_func;
+drop table test_host;
+drop table test_user;
+drop table test_db;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 7d1818ab724..06110474992 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -483,3 +483,16 @@ select col1 n from t1 union select col2 n from t1 order by n;
alter table t1 add index myindex (col2);
select col1 n from t1 union select col2 n from t1 order by n;
drop table t1;
+
+#
+# Bug #1428, incorrect handling of UNION ALL
+# NOTE: The current result is wrong, needs to be fixed!
+#
+
+create table t1 (i int);
+insert into t1 values (1);
+select * from t1 UNION select * from t1;
+select * from t1 UNION ALL select * from t1;
+# The following should return 2 lines
+select * from t1 UNION select * from t1 UNION ALL select * from t1;
+drop table t1;
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 05ac0427a92..26eacb86164 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -270,6 +270,18 @@ select 1;
--error 1238
select @@session.key_buffer_size;
+--error 1229
+set ft_boolean_syntax = @@init_connect;
+--error 1231
+set global ft_boolean_syntax = @@init_connect;
+--error 1229
+set init_connect = NULL;
+set global init_connect = NULL;
+--error 1229
+set ft_boolean_syntax = @@init_connect;
+--error 1231
+set global ft_boolean_syntax = @@init_connect;
+
#
# swap
#
@@ -285,3 +297,17 @@ select @@global.max_user_connections,@@local.max_join_size;
set @a=1, @b=2;
set @a=@b, @b=@a;
select @a, @b;
+
+#
+# Bug#2586:Disallow global/session/local as structured var. instance names
+#
+--error 1064
+set @@global.global.key_buffer_size= 1;
+--error 1064
+set GLOBAL global.key_buffer_size= 1;
+--error 1064
+SELECT @@global.global.key_buffer_size;
+--error 1064
+SELECT @@global.session.key_buffer_size;
+--error 1064
+SELECT @@global.local.key_buffer_size;
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 77b17d28ba3..d4290bbc49b 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -34,7 +34,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \
my_alloc.c safemalloc.c my_new.cc \
- my_fopen.c my_fstream.c \
+ my_fopen.c my_fstream.c my_getsystime.c \
my_error.c errors.c my_div.c my_messnc.c \
mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
my_symlink.c my_symlink2.c \
diff --git a/mysys/charset.c b/mysys/charset.c
index 5bf0ea972a5..c422ead89c0 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -62,7 +62,7 @@ static void set_max_sort_char(CHARSET_INFO *cs)
if ((uchar) cs->sort_order[i] > max_char)
{
max_char=(uchar) cs->sort_order[i];
- cs->max_sort_char= (char) i;
+ cs->max_sort_char= i;
}
}
}
diff --git a/mysys/charset2html.c b/mysys/charset2html.c
index 64021689bea..55c39ae419d 100644
--- a/mysys/charset2html.c
+++ b/mysys/charset2html.c
@@ -84,14 +84,14 @@ static void print_cs(CHARSET_INFO *cs)
printf("<TD>%02X",ch[i].srt);
printf("<TD>%s%s%s%s%s%s%s%s",
- ch[i].ctp & _U ? "U" : "",
- ch[i].ctp & _L ? "L" : "",
- ch[i].ctp & _NMR ? "N" : "",
- ch[i].ctp & _SPC ? "S" : "",
- ch[i].ctp & _PNT ? "P" : "",
- ch[i].ctp & _CTR ? "C" : "",
- ch[i].ctp & _B ? "B" : "",
- ch[i].ctp & _X ? "X" : "");
+ ch[i].ctp & _MY_U ? "U" : "",
+ ch[i].ctp & _MY_L ? "L" : "",
+ ch[i].ctp & _MY_NMR ? "N" : "",
+ ch[i].ctp & _MY_SPC ? "S" : "",
+ ch[i].ctp & _MY_PNT ? "P" : "",
+ ch[i].ctp & _MY_CTR ? "C" : "",
+ ch[i].ctp & _MY_B ? "B" : "",
+ ch[i].ctp & _MY_X ? "X" : "");
printf("<TD>&#%d;",ch[i].uni);
printf("<TD>&#%d;",ch[i].low);
diff --git a/mysys/hash.c b/mysys/hash.c
index 4ef8847363f..b7be41a9058 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -122,7 +122,7 @@ static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax,
-#ifndef __SUNPRO_C /* SUNPRO can't handle this */
+#if !defined(__SUNPRO_C) && !defined(__USLC__) /* broken compilers */
inline
#endif
unsigned int rec_hashnr(HASH *hash,const byte *record)
@@ -215,9 +215,9 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length)
{
uint rec_keylength;
byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1);
- return (length && length != rec_keylength) ||
- my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength,
- (uchar*) key, length);
+ return ((length && length != rec_keylength) ||
+ my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength,
+ (uchar*) key, length));
}
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index f64dc5abf2d..d2c373ab0c6 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -987,7 +987,7 @@ int my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count)
Buffer+=rest_length;
Count-=rest_length;
info->write_pos+=rest_length;
- if (_flush_io_cache(info,0))
+ if (my_b_flush_io_cache(info,0))
{
unlock_append_buffer(info);
return 1;
@@ -1094,12 +1094,12 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count,
#endif
-int _flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
+int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
{
uint length;
my_bool append_cache;
my_off_t pos_in_file;
- DBUG_ENTER("_flush_io_cache");
+ DBUG_ENTER("my_b_flush_io_cache");
if (!(append_cache = (info->type == SEQ_READ_APPEND)))
need_append_buffer_lock=0;
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index 638bbaf7baf..2d0a5ea282b 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -347,11 +347,25 @@ static my_string NEAR_F expand_tilde(my_string *path)
return (my_string) 0;
}
- /* fix filename so it can be used by open, create .. */
- /* to may be == from */
- /* Returns to */
-my_string unpack_filename(my_string to, const char *from)
+/*
+ Fix filename so it can be used by open, create
+
+ SYNOPSIS
+ unpack_filename()
+ to Store result here. Must be at least of size FN_REFLEN.
+ from Filename in unix format (with ~)
+
+ RETURN
+ # length of to
+
+ NOTES
+ to may be == from
+ ~ will only be expanded if total length < FN_REFLEN
+*/
+
+
+uint unpack_filename(my_string to, const char *from)
{
uint length,n_length;
char buff[FN_REFLEN];
@@ -362,17 +376,17 @@ my_string unpack_filename(my_string to, const char *from)
if (n_length+strlen(from+length) < FN_REFLEN)
{
(void) strmov(buff+n_length,from+length);
- (void) system_filename(to,buff); /* Fix to usably filename */
+ length= system_filename(to,buff); /* Fix to usably filename */
}
else
- (void) system_filename(to,from); /* Fix to usably filename */
- DBUG_RETURN(to);
+ length= system_filename(to,from); /* Fix to usably filename */
+ DBUG_RETURN(length);
} /* unpack_filename */
/* Convert filename (unix standard) to system standard */
/* Used before system command's like open(), create() .. */
- /* Returns to */
+ /* Returns length of to */
uint system_filename(my_string to, const char *from)
{
diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c
index 459e304dfd7..75d9270c5af 100644
--- a/mysys/mf_soundex.c
+++ b/mysys/mf_soundex.c
@@ -28,6 +28,10 @@
* *
* As an extension if remove_garbage is set then all non- *
* alpha characters are skipped *
+* *
+* Note, that this implementation corresponds to the *
+* original version of the algorithm, not to the more *
+* popular "enhanced" version, described by Knuth. *
****************************************************************/
#include "mysys_priv.h"
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 3eacfbddd7c..8a1f6db6f8a 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -657,18 +657,15 @@ static longlong eval_num_suffix (char *argument, int *error, char *option_name)
static longlong getopt_ll(char *arg, const struct my_option *optp, int *err)
{
longlong num;
+ ulonglong block_size= (optp->block_size ? (ulonglong) optp->block_size : 1L);
num= eval_num_suffix(arg, err, (char*) optp->name);
- if (num < (longlong) optp->min_value)
- num= (longlong) optp->min_value;
- else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value
- && optp->max_value) /* if max value is not set -> no upper limit */
+ if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value &&
+ optp->max_value) /* if max value is not set -> no upper limit */
num= (longlong) (ulong) optp->max_value;
- num= ((num - (longlong) optp->sub_size) / (optp->block_size ?
- (ulonglong) optp->block_size :
- 1L));
- return (longlong) (num * (optp->block_size ? (ulonglong) optp->block_size :
- 1L));
+ num= ((num - (longlong) optp->sub_size) / block_size);
+ num= (longlong) (num * block_size);
+ return max(num, optp->min_value);
}
/*
diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c
new file mode 100644
index 00000000000..bdaa232d560
--- /dev/null
+++ b/mysys/my_getsystime.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* get time since epoc in 100 nanosec units */
+/* thus to get the current time we should use the system function
+ with the highest possible resolution */
+
+#ifdef __NETWARE__
+#include <nks/time.h>
+#endif
+
+#include "mysys_priv.h"
+ulonglong my_getsystime()
+{
+#ifdef HAVE_CLOCK_GETTIME
+ struct timespec tp;
+ clock_gettime(CLOCK_REALTIME, &tp);
+ return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100;
+#elif defined(__WIN__)
+ /* TODO: use GetSystemTimeAsFileTime here or
+ QueryPerformanceCounter/QueryPerformanceFrequency */
+ struct _timeb tb;
+ _ftime(&tb);
+ return (ulonglong)tb.time*10000000+(ulonglong)tb.millitm*10000;
+#elif defined(__NETWARE__)
+ NXTime_t tm;
+ NXGetTime(NX_SINCE_1970, NX_NSECONDS, &tm);
+ return (ulonglong)tm/100;
+#else
+ /* TODO: check for other possibilities for hi-res timestamping */
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (ulonglong)tv.tv_sec*10000000+(ulonglong)tv.tv_usec*10;
+#endif
+}
diff --git a/mysys/test_fn.c b/mysys/test_fn.c
index 5a0546392ab..d0fb9f59fd6 100644
--- a/mysys/test_fn.c
+++ b/mysys/test_fn.c
@@ -59,7 +59,8 @@ int main(int argc __attribute__((unused)), char **argv)
printf("org : '%s'\n",*pos);
printf("pack: '%s'\n",fn_format(buff,*pos,"","",8));
printf("unpack: '%s'\n",fn_format(buff2,*pos,"","",4));
- if (strcmp(unpack_filename(buff,buff),buff2) != 0)
+ unpack_filename(buff,buff);
+ if (strcmp(buff,buff2) != 0)
{
printf("error on cmp: '%s' != '%s'\n",buff,buff2);
}
diff --git a/mysys/tree.c b/mysys/tree.c
index 42c58131100..0b30ffa4971 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -170,8 +170,8 @@ void delete_tree(TREE* tree)
void reset_tree(TREE* tree)
{
+ /* do not free mem_root, just mark blocks as free */
free_tree(tree, MYF(MY_MARK_BLOCKS_FREE));
- /* do not my_free() mem_root if applicable, just mark blocks as free */
}
@@ -188,10 +188,14 @@ static void delete_tree_element(TREE *tree, TREE_ELEMENT *element)
}
}
- /* Code for insert, search and delete of elements */
- /* parent[0] = & parent[-1][0]->left ||
- parent[0] = & parent[-1][0]->right */
+/*
+ insert, search and delete of elements
+
+ The following should be true:
+ parent[0] = & parent[-1][0]->left ||
+ parent[0] = & parent[-1][0]->right
+*/
TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
void* custom_arg)
@@ -232,8 +236,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
if (tree->with_delete)
element=(TREE_ELEMENT *) my_malloc(alloc_size, MYF(MY_WME));
else
- element=(TREE_ELEMENT *)
- alloc_root(&tree->mem_root,alloc_size);
+ element=(TREE_ELEMENT *) alloc_root(&tree->mem_root,alloc_size);
if (!element)
return(NULL);
**parent=element;
@@ -251,9 +254,9 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
}
else
memcpy((byte*) element+tree->offset_to_key,key,(size_t) key_size);
- element->count=1; /* May give warning in purify */
+ element->count=1; /* May give warning in purify */
tree->elements_in_tree++;
- rb_insert(tree,parent,element); /* rebalance tree */
+ rb_insert(tree,parent,element); /* rebalance tree */
}
else
{
@@ -320,6 +323,8 @@ int tree_delete(TREE *tree, void *key, void *custom_arg)
rb_delete_fixup(tree,parent);
if (tree->free)
(*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
+ /* This doesn't include key_size, but better than nothing */
+ tree->allocated-= sizeof(TREE_ELEMENT)+tree->size_of_element;
my_free((gptr) element,MYF(0));
tree->elements_in_tree--;
return 0;
diff --git a/pstack/bucomm.h b/pstack/bucomm.h
index 7712a70f5a2..6b3633d8d63 100644
--- a/pstack/bucomm.h
+++ b/pstack/bucomm.h
@@ -50,6 +50,12 @@ void *alloca ();
# endif /* HAVE_ALLOCA_H */
#endif
+#ifndef BFD_TRUE_FALSE
+#define boolean bfd_boolean
+#define true TRUE
+#define false FALSE
+#endif
+
/* bucomm.c */
void bfd_nonfatal PARAMS ((CONST char *));
diff --git a/pstack/budbg.h b/pstack/budbg.h
index d8ee8895e76..9f0203ad5e7 100644
--- a/pstack/budbg.h
+++ b/pstack/budbg.h
@@ -24,6 +24,12 @@
#include <stdio.h>
+#ifndef BFD_TRUE_FALSE
+#define boolean bfd_boolean
+#define true TRUE
+#define false FALSE
+#endif
+
/* Routine used to read generic debugging information. */
extern PTR read_debugging_info PARAMS ((bfd *, asymbol **, long));
diff --git a/pstack/pstack.c b/pstack/pstack.c
index 48280d4aedb..75869686e35 100644
--- a/pstack/pstack.c
+++ b/pstack/pstack.c
@@ -2667,7 +2667,8 @@ pstack_install_segv_action( const char* path_format_)
if ((abfd = load_bfd(pid))==0)
fprintf(stderr, "BFD load failed..\n");
else {
- long storage_needed = bfd_get_symtab_upper_bound (abfd);
+ long storage_needed= (bfd_get_file_flags(abfd) & HAS_SYMS) ?
+ bfd_get_symtab_upper_bound (abfd) : 0;
long i;
(void)i;
diff --git a/regex/regcomp.c b/regex/regcomp.c
index 6af99456c28..b939429e16e 100644
--- a/regex/regcomp.c
+++ b/regex/regcomp.c
@@ -36,18 +36,18 @@ struct parse {
static char nuls[10]; /* place to point scanner in event of error */
struct cclass cclasses[CCLASS_LAST+1]= {
- { "alnum", "","", _U | _L | _NMR},
- { "alpha", "","", _U | _L },
- { "blank", "","", _B },
- { "cntrl", "","", _CTR },
- { "digit", "","", _NMR },
- { "graph", "","", _PNT | _U | _L | _NMR},
- { "lower", "","", _L },
- { "print", "","", _PNT | _U | _L | _NMR | _B },
- { "punct", "","", _PNT },
- { "space", "","", _SPC },
- { "upper", "","", _U },
- { "xdigit", "","", _X },
+ { "alnum", "","", _MY_U | _MY_L | _MY_NMR},
+ { "alpha", "","", _MY_U | _MY_L },
+ { "blank", "","", _MY_B },
+ { "cntrl", "","", _MY_CTR },
+ { "digit", "","", _MY_NMR },
+ { "graph", "","", _MY_PNT | _MY_U | _MY_L | _MY_NMR},
+ { "lower", "","", _MY_L },
+ { "print", "","", _MY_PNT | _MY_U | _MY_L | _MY_NMR | _MY_B },
+ { "punct", "","", _MY_PNT },
+ { "space", "","", _MY_SPC },
+ { "upper", "","", _MY_U },
+ { "xdigit", "","", _MY_X },
{ NULL,NULL,NULL, 0 }
};
diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh
index a65004bec4c..5129c028238 100644
--- a/scripts/mysql_create_system_tables.sh
+++ b/scripts/mysql_create_system_tables.sh
@@ -188,7 +188,7 @@ then
c_t="$c_t Host char(60) binary DEFAULT '' NOT NULL,"
c_t="$c_t Db char(64) binary DEFAULT '' NOT NULL,"
c_t="$c_t User char(16) binary DEFAULT '' NOT NULL,"
- c_t="$c_t Table_name char(60) binary DEFAULT '' NOT NULL,"
+ c_t="$c_t Table_name char(64) binary DEFAULT '' NOT NULL,"
c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL,"
c_t="$c_t Timestamp timestamp(14),"
c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL,"
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index bf7f082203d..69bf2bebaa8 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -10,6 +10,10 @@ sql_only=0
basedir=""
verbose=0
args=""
+port=""
+socket=""
+database="mysql"
+bindir=""
file=mysql_fix_privilege_tables.sql
@@ -34,6 +38,10 @@ parse_arguments() {
--host=*) host=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
--sql|--sql-only) sql_only=1;;
--verbose) verbose=1 ;;
+ --port=*) port=`echo "$arg" | sed -e "s;--port=;;"` ;;
+ --socket=*) socket=`echo "$arg" | sed -e "s;--socket=;;"` ;;
+ --database=*) database=`echo "$arg" | sed -e "s;--database=;;"` ;;
+ --bindir=*) bindir=`echo "$arg" | sed -e "s;--bindir=;;"` ;;
*)
if test -n "$pick_args"
then
@@ -48,21 +56,15 @@ parse_arguments() {
# Get first arguments from the my.cfg file, groups [mysqld] and
# [mysql_install_db], and then merge with the command line arguments
-if test -x ./bin/my_print_defaults
-then
- print_defaults="./bin/my_print_defaults"
-elif test -x @bindr@/my_print_defaults
-then
- print_defaults="@bindir@/my_print_defaults"
-elif test -x @bindir@/mysql_print_defaults
-then
- print_defaults="@bindir@/mysql_print_defaults"
-elif test -x extra/my_print_defaults
-then
- print_defaults="extra/my_print_defaults"
-else
- print_defaults="my_print_defaults"
-fi
+
+for dir in ./bin @bindir@ @bindir@ extra $bindir/../bin $bindir/../extra
+do
+ if test -x $dir/my_print_defaults
+ then
+ print_defaults="$dir/my_print_defaults"
+ break
+ fi
+done
parse_arguments `$print_defaults $defaults mysql_install_db mysql_fix_privilege_tables`
parse_arguments PICK-ARGS-FROM-ARGV "$@"
@@ -70,11 +72,17 @@ parse_arguments PICK-ARGS-FROM-ARGV "$@"
if test -z "$basedir"
then
basedir=@prefix@
- bindir=@bindir@
+ if test -z "$bindir"
+ then
+ bindir=@bindir@
+ fi
execdir=@libexecdir@
pkgdatadir=@pkgdatadir@
else
- bindir="$basedir/bin"
+ if test -z "$bindir"
+ then
+ bindir="$basedir/bin"
+ fi
if test -x "$basedir/libexec/mysqld"
then
execdir="$basedir/libexec"
@@ -93,11 +101,18 @@ then
password=`echo $args | sed -e 's/ *//g'`
fi
+cmd="$bindir/mysql -f --user=$user --host=$host"
if test -z "$password" ; then
- cmd="$bindir/mysql -f --user=$user --host=$host mysql"
-else
- cmd="$bindir/mysql -f --user=$user --password=$password --host=$host mysql"
+ cmd="$cmd --password=$password"
+fi
+if test ! -z "$port"; then
+ cmd="$cmd --port=$port"
fi
+if test ! -z "$socket"; then
+ cmd="$cmd --socket=$socket"
+fi
+cmd="$cmd --database=$database"
+
if test $sql_only = 1
then
cmd="cat"
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index de5779b9ac0..dabc653bcbb 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -7,19 +7,18 @@
-- On unix, you should use the mysql_fix_privilege_tables script to execute
-- this sql script.
--- On windows you should do 'mysql --force < mysql_fix_privilege_tables.sql'
+-- On windows you should do 'mysql --force mysql < mysql_fix_privilege_tables.sql'
-USE mysql;
ALTER TABLE user type=MyISAM;
ALTER TABLE db type=MyISAM;
ALTER TABLE host type=MyISAM;
ALTER TABLE func type=MyISAM;
ALTER TABLE columns_priv type=MyISAM;
ALTER TABLE tables_priv type=MyISAM;
-ALTER TABLE user change Password Password char(41) not null;
+ALTER TABLE user change Password Password char(41) binary not null;
ALTER TABLE user add File_priv enum('N','Y') NOT NULL;
CREATE TABLE IF NOT EXISTS func (
- name char(64) DEFAULT '' NOT NULL,
+ name char(64) binary DEFAULT '' NOT NULL,
ret tinyint(1) DEFAULT '0' NOT NULL,
dl char(128) DEFAULT '' NOT NULL,
type enum ('function','aggregate') NOT NULL,
@@ -39,6 +38,10 @@ UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Crea
UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0;
UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0;
+--
+-- The second alter changes ssl_type to new 4.0.2 format
+-- Adding columns needed by GRANT .. REQUIRE (openssl)"
+
ALTER TABLE user
ADD ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL,
ADD ssl_cipher BLOB NOT NULL,
@@ -46,11 +49,15 @@ ADD x509_issuer BLOB NOT NULL,
ADD x509_subject BLOB NOT NULL;
ALTER TABLE user MODIFY ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL;
+--
+-- Create tables_priv and columns_priv if they don't exists
+--
+
CREATE TABLE IF NOT EXISTS tables_priv (
- Host char(60) DEFAULT '' NOT NULL,
- Db char(60) DEFAULT '' NOT NULL,
- User char(16) DEFAULT '' NOT NULL,
- Table_name char(60) DEFAULT '' NOT NULL,
+ Host char(60) binary DEFAULT '' NOT NULL,
+ Db char(64) binary DEFAULT '' NOT NULL,
+ User char(16) binary DEFAULT '' NOT NULL,
+ Table_name char(64) binary DEFAULT '' NOT NULL,
Grantor char(77) DEFAULT '' NOT NULL,
Timestamp timestamp(14),
Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL,
@@ -69,16 +76,29 @@ CREATE TABLE IF NOT EXISTS columns_priv (
PRIMARY KEY (Host,Db,User,Table_name,Column_name)
);
+
+--
+-- Name change of Type -> Column_priv from MySQL 3.22.12
+--
+
ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL;
+--
+-- Add the new 'type' column to the func table.
+--
+
ALTER TABLE func add type enum ('function','aggregate') NOT NULL;
+--
+-- Change the user,db and host tables to MySQL 4.0 format
+--
+
# Detect whether we had Show_db_priv
SET @hadShowDbPriv:=0;
SELECT @hadShowDbPriv:=1 FROM user WHERE Show_db_priv LIKE '%';
ALTER TABLE user
-ADD Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER alter_priv,
+ADD Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Alter_priv,
ADD Super_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Show_db_priv,
ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Super_priv,
ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Create_tmp_table_priv,
@@ -86,13 +106,24 @@ ADD Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv,
ADD Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Execute_priv,
ADD Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_slave_priv;
-UPDATE user SET show_db_priv= select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>"" AND @hadShowDbPriv = 0;
+-- Convert privileges so that users have similar privileges as before
+
+UPDATE user SET Show_db_priv= Select_priv, Super_priv=Process_priv, Execute_priv=Process_priv, Create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=File_priv where user<>"" AND @hadShowDbPriv = 0;
+
+
+-- Add fields that can be used to limit number of questions and connections
+-- for some users.
ALTER TABLE user
ADD max_questions int(11) NOT NULL AFTER x509_subject,
ADD max_updates int(11) unsigned NOT NULL AFTER max_questions,
ADD max_connections int(11) unsigned NOT NULL AFTER max_updates;
+
+--
+-- Add Create_tmp_table_priv and Lock_tables_priv to db and host
+--
+
ALTER TABLE db
ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
@@ -100,6 +131,20 @@ ALTER TABLE host
ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
+alter table db change Db Db char(64) binary DEFAULT '' NOT NULL;
+alter table host change Db Db char(64) binary DEFAULT '' NOT NULL;
+alter table user change max_questions max_questions int(11) unsigned DEFAULT 0 NOT NULL;
+alter table tables_priv change Db Db char(64) binary DEFAULT '' NOT NULL, change Host Host char(60) binary DEFAULT '' NOT NULL, change User User char(16) binary DEFAULT '' NOT NULL, change Table_name Table_name char(64) binary DEFAULT '' NOT NULL;
+alter table tables_priv add KEY Grantor (Grantor);
+alter table columns_priv change Db Db char(64) binary DEFAULT '' NOT NULL, change Host Host char(60) binary DEFAULT '' NOT NULL, change User User char(16) binary DEFAULT '' NOT NULL, change Table_name Table_name char(64) binary DEFAULT '' NOT NULL, change Column_name Column_name char(64) binary DEFAULT '' NOT NULL;
+
+alter table db comment='Database privileges';
+alter table host comment='Host privileges; Merged with database privileges';
+alter table user comment='Users and global privileges';
+alter table func comment='User defined functions';
+alter table tables_priv comment='Table privileges';
+alter table columns_priv comment='Column privileges';
+
#
# Create some possible missing tables
#
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index c593957b78d..1861e8c52f8 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -151,7 +151,7 @@ then
if [ $? -ne 0 ]
then
resolved=`$bindir/resolveip localhost 2>&1`
- if [ $? -eq 0 ]
+ if [ $? -ne 0 ]
then
echo "Neither host '$hostname' and 'localhost' could not be looked up with"
echo "$bindir/resolveip"
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index 654e5466e12..ab06215c3ac 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -37,7 +37,7 @@ WARNING: THIS PROGRAM IS STILL IN BETA. Comments/patches welcome.
# Documentation continued at end of file
-my $VERSION = "1.20";
+my $VERSION = "1.21";
my $opt_tmpdir = $ENV{TMPDIR} || "/tmp";
@@ -73,6 +73,7 @@ Usage: $0 db_name[./table_regex/] [new_db_name | directory]
--resetslave reset the master.info once all tables are locked
--tmpdir=# temporary directory (instead of $opt_tmpdir)
--record_log_pos=# record slave and master status in specified db.table
+ --chroot=# base directory of chroot jail in which mysqld operates
Try \'perldoc $0 for more complete documentation\'
_OPTIONS
@@ -117,6 +118,7 @@ GetOptions( \%opt,
"resetslave",
"tmpdir|t=s",
"dryrun|n",
+ "chroot=s",
) or usage("Invalid option");
# @db_desc
@@ -210,6 +212,7 @@ while ( my ($var,$value) = $sth_vars->fetchrow_array ) {
}
my $datadir = $mysqld_vars{'datadir'}
|| die "datadir not in mysqld variables";
+ $datadir= $opt{chroot}.$datadir if ($opt{chroot});
$datadir =~ s:/$::;
diff --git a/sql-common/client.c b/sql-common/client.c
index a22ac22f08a..27492e8d405 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -585,11 +585,8 @@ net_safe_read(MYSQL *mysql)
return (packet_error);
#endif /*MYSQL_SERVER*/
end_server(mysql);
- net->last_errno=(net->last_errno == ER_NET_PACKET_TOO_LARGE ?
- CR_NET_PACKET_TOO_LARGE:
- CR_SERVER_LOST);
- strmov(net->last_error,ER(net->last_errno));
- strmov(net->sqlstate, unknown_sqlstate);
+ set_mysql_error(mysql, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
+ CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
return (packet_error);
}
if (net->read_pos[0] == 255)
@@ -609,11 +606,8 @@ net_safe_read(MYSQL *mysql)
min((uint) len,(uint) sizeof(net->last_error)-1));
}
else
- {
- net->last_errno=CR_UNKNOWN_ERROR;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
- }
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+
DBUG_PRINT("error",("Got error: %d/%s (%s)",
net->last_errno, net->sqlstate, net->last_error));
return(packet_error);
@@ -649,8 +643,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
}
if (mysql->status != MYSQL_STATUS_READY)
{
- strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
- strmov(net->sqlstate, unknown_sqlstate);
+ set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
return 1;
}
@@ -704,6 +697,52 @@ void free_old_query(MYSQL *mysql)
DBUG_VOID_RETURN;
}
+/*
+ Set the internal error message to mysql handler
+*/
+
+void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
+{
+ NET *net;
+ DBUG_ENTER("set_mysql_error");
+ DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode)));
+ DBUG_ASSERT(mysql != 0);
+
+ net= &mysql->net;
+ net->last_errno= errcode;
+ strmov(net->last_error, ER(errcode));
+ strmov(net->sqlstate, sqlstate);
+
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Flush result set sent from server
+*/
+
+void flush_use_result(MYSQL *mysql)
+{
+ /* Clear the current execution status */
+ DBUG_PRINT("warning",("Not all packets read, clearing them"));
+ for (;;)
+ {
+ ulong pkt_len;
+ if ((pkt_len=net_safe_read(mysql)) == packet_error)
+ break;
+ if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
+ {
+ if (protocol_41(mysql))
+ {
+ char *pos= (char*) mysql->net.read_pos;
+ mysql->warning_count=uint2korr(pos); pos+=2;
+ mysql->server_status=uint2korr(pos); pos+=2;
+ }
+ break; /* End of data */
+ }
+ }
+}
+
+
#ifdef __WIN__
static my_bool is_NT(void)
{
@@ -741,26 +780,16 @@ mysql_free_result(MYSQL_RES *result)
DBUG_PRINT("enter",("mysql_res: %lx",result));
if (result)
{
- if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
+ MYSQL *mysql= result->handle;
+ if (mysql)
{
- DBUG_PRINT("warning",("Not all rows in set where read; Ignoring rows"));
- for (;;)
+ if (mysql->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
+ mysql->unbuffered_fetch_owner= 0;
+ if (mysql->status == MYSQL_STATUS_USE_RESULT)
{
- ulong pkt_len;
- if ((pkt_len=net_safe_read(result->handle)) == packet_error)
- break;
- if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254)
- {
- if (protocol_41(result->handle))
- {
- char *pos= (char*) result->handle->net.read_pos;
- result->handle->warning_count=uint2korr(pos); pos+=2;
- result->handle->server_status=uint2korr(pos); pos+=2;
- }
- break; /* End of data */
- }
+ flush_use_result(mysql);
+ mysql->status=MYSQL_STATUS_READY;
}
- result->handle->status=MYSQL_STATUS_READY;
}
free_rows(result->data);
if (result->fields)
@@ -1164,9 +1193,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
MYF(MY_WME | MY_ZEROFILL))))
{
- net->last_errno=CR_OUT_OF_MEMORY;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(0);
}
init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
@@ -1193,9 +1220,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
(fields+1)*sizeof(char *)+pkt_len))))
{
free_rows(result);
- net->last_errno=CR_OUT_OF_MEMORY;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(0);
}
*prev_ptr=cur;
@@ -1214,9 +1239,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
if (len > (ulong) (end_to - to))
{
free_rows(result);
- net->last_errno=CR_MALFORMED_PACKET;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
DBUG_RETURN(0);
}
memcpy(to,(char*) cp,len); to[len]=0;
@@ -1287,9 +1310,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
{
if (len > (ulong) (end_pos - pos))
{
- net->last_errno=CR_UNKNOWN_ERROR;
- strmov(net->last_error,ER(net->last_errno));
- strmov(net->sqlstate, unknown_sqlstate);
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
return -1;
}
row[field] = (char*) pos;
@@ -1422,7 +1443,7 @@ static MYSQL_METHODS client_methods=
cli_read_binary_rows,
cli_unbuffered_fetch,
NULL,
- cli_read_statistic,
+ cli_read_statistics,
cli_read_query_result,
cli_read_change_user_result
#endif
@@ -1675,9 +1696,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
if (!net->vio)
{
DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol));
- strmov(net->sqlstate, unknown_sqlstate);
- net->last_errno= CR_CONN_UNKNOW_PROTOCOL;
- strmov(net->last_error, ER(CR_CONN_UNKNOW_PROTOCOL));
+ set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
goto error;
}
@@ -1685,9 +1704,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
{
vio_delete(net->vio);
net->vio = 0;
- net->last_errno=CR_OUT_OF_MEMORY;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
goto error;
}
vio_keepalive(net->vio,TRUE);
@@ -1704,9 +1721,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
if (mysql->options.connect_timeout &&
vio_poll_read(net->vio, mysql->options.connect_timeout))
{
- net->last_errno= CR_SERVER_LOST;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
goto error;
}
@@ -1760,8 +1775,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
if (mysql->options.secure_auth && passwd[0] &&
!(mysql->server_capabilities & CLIENT_SECURE_CONNECTION))
{
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error, ER(net->last_errno=CR_SECURE_AUTH));
+ set_mysql_error(mysql, CR_SECURE_AUTH, unknown_sqlstate);
goto error;
}
@@ -1815,8 +1829,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
!(mysql->user=my_strdup(user,MYF(0))) ||
!(mysql->passwd=my_strdup(passwd,MYF(0))))
{
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY));
+ set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
goto error;
}
strmov(mysql->host_info,host_info);
@@ -1883,9 +1896,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
struct st_mysql_options *options= &mysql->options;
if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net))
{
- strmov(net->sqlstate, unknown_sqlstate);
- net->last_errno= CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
goto error;
}
/* Do the SSL layering. */
@@ -1896,18 +1907,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
options->ssl_capath,
options->ssl_cipher)))
{
- strmov(net->sqlstate, unknown_sqlstate);
- net->last_errno= CR_SSL_CONNECTION_ERROR;
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
goto error;
}
DBUG_PRINT("info", ("IO layer change in progress..."));
if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),
mysql->net.vio, (long) (mysql->options.connect_timeout)))
{
- strmov(net->sqlstate, unknown_sqlstate);
- net->last_errno= CR_SSL_CONNECTION_ERROR;
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
goto error;
}
DBUG_PRINT("info", ("IO layer change done!"));
@@ -1956,9 +1963,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
/* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
{
- strmov(net->sqlstate, unknown_sqlstate);
- net->last_errno= CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
goto error;
}
@@ -1980,9 +1985,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
scramble_323(buff, mysql->scramble, passwd);
if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
{
- net->last_errno= CR_SERVER_LOST;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
+ set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
goto error;
}
/* Read what server thinks about out new auth message report */
@@ -2077,9 +2080,7 @@ my_bool mysql_reconnect(MYSQL *mysql)
{
/* Allow reconnect next time */
mysql->server_status&= ~SERVER_STATUS_IN_TRANS;
- strmov(mysql->net.sqlstate, unknown_sqlstate);
- mysql->net.last_errno=CR_SERVER_GONE_ERROR;
- strmov(mysql->net.last_error,ER(mysql->net.last_errno));
+ set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate);
DBUG_RETURN(1);
}
mysql_init(&tmp_mysql);
@@ -2194,12 +2195,13 @@ void STDCALL mysql_close(MYSQL *mysql)
#ifdef MYSQL_CLIENT
if (mysql->stmts)
{
- /* Free any open prepared statements */
- LIST *element, *next_element;
- for (element= mysql->stmts; element; element= next_element)
+ /* Reset connection handle in all prepared statements. */
+ LIST *element;
+ for (element= mysql->stmts; element; element= element->next)
{
- next_element= element->next;
- stmt_close((MYSQL_STMT *)element->data, 0, 1);
+ MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
+ stmt->mysql= 0;
+ /* No need to call list_delete for statement here */
}
mysql->stmts= 0;
}
@@ -2231,6 +2233,7 @@ void STDCALL mysql_close(MYSQL *mysql)
DBUG_VOID_RETURN;
}
+
static my_bool cli_read_query_result(MYSQL *mysql)
{
uchar *pos;
@@ -2363,9 +2366,7 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
{
- strmov(mysql->net.sqlstate, unknown_sqlstate);
- strmov(mysql->net.last_error,
- ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
+ set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(0);
}
mysql->status=MYSQL_STATUS_READY; /* server is ready */
@@ -2374,9 +2375,7 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
mysql->field_count),
MYF(MY_WME | MY_ZEROFILL))))
{
- strmov(mysql->net.sqlstate, unknown_sqlstate);
- mysql->net.last_errno=CR_OUT_OF_MEMORY;
- strmov(mysql->net.last_error, ER(mysql->net.last_errno));
+ set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(0);
}
result->methods= mysql->methods;
@@ -2393,9 +2392,10 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
result->fields= mysql->fields;
result->field_alloc= mysql->field_alloc;
result->field_count= mysql->field_count;
- result->current_field=0;
- result->current_row=0; /* Must do a fetch first */
+ /* The rest of result members is bzeroed in malloc */
mysql->fields=0; /* fields is now in result */
+ /* just in case this was mistakenly called after mysql_stmt_execute() */
+ mysql->unbuffered_fetch_owner= 0;
DBUG_RETURN(result); /* Data fetched */
}
@@ -2421,9 +2421,7 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
{
- strmov(mysql->net.sqlstate, unknown_sqlstate);
- strmov(mysql->net.last_error,
- ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
+ set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(0);
}
if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
@@ -2446,6 +2444,7 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql)
result->current_row= 0;
mysql->fields=0; /* fields is now in result */
mysql->status=MYSQL_STATUS_USE_RESULT;
+ mysql->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
DBUG_RETURN(result); /* Data is read to be fetched */
}
@@ -2462,19 +2461,30 @@ mysql_fetch_row(MYSQL_RES *res)
{ /* Unbufferred fetch */
if (!res->eof)
{
- if (!(read_one_row(res->handle,res->field_count,res->row, res->lengths)))
+ MYSQL *mysql= res->handle;
+ if (mysql->status != MYSQL_STATUS_USE_RESULT)
{
- res->row_count++;
- DBUG_RETURN(res->current_row=res->row);
+ set_mysql_error(mysql,
+ res->unbuffered_fetch_cancelled ?
+ CR_FETCH_CANCELLED : CR_COMMANDS_OUT_OF_SYNC,
+ unknown_sqlstate);
}
- else
+ else if (!(read_one_row(mysql, res->field_count, res->row, res->lengths)))
{
- DBUG_PRINT("info",("end of data"));
- res->eof=1;
- res->handle->status=MYSQL_STATUS_READY;
- /* Don't clear handle in mysql_free_results */
- res->handle=0;
+ res->row_count++;
+ DBUG_RETURN(res->current_row=res->row);
}
+ DBUG_PRINT("info",("end of data"));
+ res->eof=1;
+ mysql->status=MYSQL_STATUS_READY;
+ /*
+ Reset only if owner points to us: there is a chance that somebody
+ started new query after mysql_stmt_close():
+ */
+ if (mysql->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
+ mysql->unbuffered_fetch_owner= 0;
+ /* Don't clear handle in mysql_free_result */
+ res->handle=0;
}
DBUG_RETURN((MYSQL_ROW) NULL);
}
@@ -2592,3 +2602,4 @@ const char * STDCALL mysql_error(MYSQL *mysql)
{
return mysql->net.last_error;
}
+
diff --git a/sql/field.cc b/sql/field.cc
index 4632fbc5c69..6a891fac5c6 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -107,7 +107,7 @@ bool test_if_int(const char *str, int length, const char *int_end,
return 1;
}
-
+#ifdef NOT_USED
static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
{
cs= system_charset_info; // QQ move test_if_real into CHARSET_INFO struct
@@ -159,7 +159,7 @@ static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
}
return 1;
}
-
+#endif
static inline uint field_length_without_space(const char *ptr, uint length)
{
@@ -2264,20 +2264,23 @@ void Field_longlong::sql_type(String &res) const
add_zerofill_and_unsigned(res);
}
+
/****************************************************************************
-** single precision float
+ single precision float
****************************************************************************/
int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
{
- int err;
- Field_float::store(my_strntod(cs,(char*) from,len,(char**)NULL,&err));
- if (err || current_thd->count_cuted_fields && !test_if_real(from,len,cs))
+ int error;
+ char *end;
+ double nr= my_strntod(cs,(char*) from,len,&end,&error);
+ if (error || ((uint) (end-from) != len && current_thd->count_cuted_fields))
{
+ error= 1;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
- return 1;
}
- return (err) ? 1 : 0;
+ Field_float::store(nr);
+ return error;
}
@@ -2285,28 +2288,48 @@ int Field_float::store(double nr)
{
float j;
int error= 0;
- if (dec < NOT_FIXED_DEC)
- nr=floor(nr*log_10[dec]+0.5)/log_10[dec]; // To fixed point
- if (unsigned_flag && nr < 0)
+
+ if (isnan(nr))
{
+ j= 0;
+ set_null();
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
- nr=0;
error= 1;
}
- if (nr < -FLT_MAX)
+ else if (unsigned_flag && nr < 0)
{
- j= -FLT_MAX;
+ j= 0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
error= 1;
}
- else if (nr > FLT_MAX)
+ else
{
- j=FLT_MAX;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
- error= 1;
+ double max_value;
+ if (dec >= NOT_FIXED_DEC)
+ {
+ max_value= FLT_MAX;
+ }
+ else
+ {
+ max_value= (log_10[field_length]-1)/log_10[dec];
+ nr= floor(nr*log_10[dec]+0.5)/log_10[dec];
+ }
+ if (nr < -max_value)
+ {
+ j= (float)-max_value;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ error= 1;
+ }
+ else if (nr > max_value)
+ {
+ j= (float)max_value;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ error= 1;
+ }
+ else
+ j= (float) nr;
}
- else
- j= (float) nr;
+
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -2537,48 +2560,69 @@ void Field_float::sql_type(String &res) const
add_zerofill_and_unsigned(res);
}
+
/****************************************************************************
-** double precision floating point numbers
+ double precision floating point numbers
****************************************************************************/
int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
{
- int err;
- double j= my_strntod(cs,(char*) from,len,(char**)0,&err);
- if (err || current_thd->count_cuted_fields && !test_if_real(from,len,cs))
+ int error;
+ char *end;
+ double nr= my_strntod(cs,(char*) from, len, &end, &error);
+ if (error || ((uint) (end-from) != len && current_thd->count_cuted_fields))
{
+ error= 1;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
- err= 1;
- }
- if (unsigned_flag && j < 0)
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
- j=0;
- err= 1;
}
-#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float8store(ptr,j);
- }
- else
-#endif
- doublestore(ptr,j);
- return err;
+ Field_double::store(nr);
+ return error;
}
int Field_double::store(double nr)
{
int error= 0;
- if (dec < NOT_FIXED_DEC)
- nr=floor(nr*log_10[dec]+0.5)/log_10[dec]; // To fixed point
- if (unsigned_flag && nr < 0)
+
+ if (isnan(nr))
{
+ nr= 0;
+ set_null();
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
- nr=0;
error= 1;
}
+ else if (unsigned_flag && nr < 0)
+ {
+ nr= 0;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ error= 1;
+ }
+ else
+ {
+ double max_value;
+ if (dec >= NOT_FIXED_DEC)
+ {
+ max_value= DBL_MAX;
+ }
+ else
+ {
+ max_value= (log_10[field_length]-1)/log_10[dec];
+ nr= floor(nr*log_10[dec]+0.5)/log_10[dec];
+ }
+ if (nr < -max_value)
+ {
+ nr= -max_value;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ error= 1;
+ }
+ else if (nr > max_value)
+ {
+ nr= max_value;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ error= 1;
+ }
+ }
+
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -4715,18 +4759,28 @@ void Field_blob::get_key_image(char *buff,uint length,
#ifdef HAVE_SPATIAL
if (type == itMBR)
{
- if (!blob_length)
+ const char *dummy;
+ MBR mbr;
+ Geometry_buffer buffer;
+ Geometry *gobj;
+
+ if (blob_length < SRID_SIZE)
+ {
+ bzero(buff, SIZEOF_STORED_DOUBLE*4);
return;
+ }
get_ptr(&blob);
-
- MBR mbr;
- Geometry gobj;
- gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE);
- gobj.get_mbr(&mbr);
- float8store(buff, mbr.xmin);
- float8store(buff+8, mbr.xmax);
- float8store(buff+16, mbr.ymin);
- float8store(buff+24, mbr.ymax);
+ gobj= Geometry::create_from_wkb(&buffer,
+ blob + SRID_SIZE, blob_length - SRID_SIZE);
+ if (gobj->get_mbr(&mbr, &dummy))
+ bzero(buff, SIZEOF_STORED_DOUBLE*4);
+ else
+ {
+ float8store(buff, mbr.xmin);
+ float8store(buff+8, mbr.xmax);
+ float8store(buff+16, mbr.ymin);
+ float8store(buff+24, mbr.ymax);
+ }
return;
}
#endif /*HAVE_SPATIAL*/
@@ -4939,6 +4993,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length;
}
+
#ifdef HAVE_SPATIAL
void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
@@ -4947,17 +5002,28 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
length-= HA_KEY_BLOB_LENGTH;
ulong blob_length= get_length(ptr);
char *blob;
- get_ptr(&blob);
-
+ const char *dummy;
MBR mbr;
- Geometry gobj;
- gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE);
- gobj.get_mbr(&mbr);
- float8store(buff, mbr.xmin);
- float8store(buff + 8, mbr.xmax);
- float8store(buff + 16, mbr.ymin);
- float8store(buff + 24, mbr.ymax);
- return;
+
+ if (blob_length < SRID_SIZE)
+ {
+ bzero(buff, SIZEOF_STORED_DOUBLE*4);
+ return;
+ }
+ get_ptr(&blob);
+ Geometry_buffer buffer;
+ Geometry *gobj;
+ gobj= Geometry::create_from_wkb(&buffer,
+ blob + SRID_SIZE, blob_length - SRID_SIZE);
+ if (gobj->get_mbr(&mbr, &dummy))
+ bzero(buff, SIZEOF_STORED_DOUBLE*4);
+ else
+ {
+ float8store(buff, mbr.xmin);
+ float8store(buff + 8, mbr.xmax);
+ float8store(buff + 16, mbr.ymin);
+ float8store(buff + 24, mbr.ymax);
+ }
}
@@ -5001,17 +5067,17 @@ void Field_geom::sql_type(String &res) const
int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
{
if (!length)
- {
bzero(ptr, Field_blob::pack_length());
- }
else
{
- // Should check given WKB
- if (length < 4 + 1 + 4 + 8 + 8) // SRID + WKB_HEADER + X + Y
- return 1;
- uint32 wkb_type= uint4korr(from + 5);
- if (wkb_type < 1 || wkb_type > 7)
- return 1;
+ // Check given WKB
+ uint32 wkb_type;
+ if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2)
+ goto err;
+ wkb_type= uint4korr(from + WKB_HEADER_SIZE);
+ if (wkb_type < (uint32) Geometry::wkb_point ||
+ wkb_type > (uint32) Geometry::wkb_end)
+ return -1;
Field_blob::store_length(length);
if (table->copy_blobs || length <= MAX_FIELD_WIDTH)
{ // Must make a copy
@@ -5021,6 +5087,10 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
bmove(ptr + packlength, (char*) &from, sizeof(char*));
}
return 0;
+
+err:
+ bzero(ptr, Field_blob::pack_length());
+ return -1;
}
#endif /*HAVE_SPATIAL*/
@@ -5663,7 +5733,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
{
pos= (char*) sql_memdup(tmp.ptr(),tmp.length()+1);
pos[tmp.length()]=0;
- def=new Item_string(pos,tmp.length(), charset);
+ def= new Item_string(pos, tmp.length(), charset);
}
}
#ifdef HAVE_SPATIAL
diff --git a/sql/field.h b/sql/field.h
index f815324c698..22d406b339a 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1184,8 +1184,8 @@ Field *make_field(char *ptr, uint32 field_length,
struct st_table *table);
uint pack_length_to_packflag(uint type);
uint32 calc_pack_length(enum_field_types type,uint32 length);
-bool set_field_to_null(Field *field);
-bool set_field_to_null_with_conversions(Field *field, bool no_conversions);
+int set_field_to_null(Field *field);
+int set_field_to_null_with_conversions(Field *field, bool no_conversions);
bool test_if_int(const char *str, int length, const char *int_end,
CHARSET_INFO *cs);
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 67905d35e0d..3272c2faf48 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -109,7 +109,7 @@ static void do_outer_field_to_null_str(Copy_field *copy)
}
-bool
+int
set_field_to_null(Field *field)
{
if (field->real_maybe_null())
@@ -127,7 +127,7 @@ set_field_to_null(Field *field)
if (!current_thd->no_errors)
my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
field->field_name);
- return 1;
+ return -1;
}
@@ -145,11 +145,11 @@ set_field_to_null(Field *field)
RETURN VALUES
0 Field could take 0 or an automatic conversion was used
- 1 Field could not take NULL and no conversion was used.
+ -1 Field could not take NULL and no conversion was used.
If no_conversion was not set, an error message is printed
*/
-bool
+int
set_field_to_null_with_conversions(Field *field, bool no_conversions)
{
if (field->real_maybe_null())
@@ -159,7 +159,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions)
return 0;
}
if (no_conversions)
- return 1;
+ return -1;
/*
Check if this is a special type, which will get a special walue
@@ -184,7 +184,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions)
if (!current_thd->no_errors)
my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
field->field_name);
- return 1;
+ return -1;
}
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 6df7d867a4d..5dc7c50e04c 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -81,7 +81,6 @@ TODO:
#endif
#include <my_getopt.h>
#include "mysql_version.h"
-#include "mysql_priv.h"
#include "lex.h"
struct my_option my_long_options[] =
diff --git a/sql/gstream.cc b/sql/gstream.cc
index 17b85af22bd..f7d11d76b0c 100644
--- a/sql/gstream.cc
+++ b/sql/gstream.cc
@@ -1,139 +1,120 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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 */
+
+/*
+ Functions to read and parse geometrical data.
+ NOTE: These functions assumes that the string is end \0 terminated!
+*/
+
#include "mysql_priv.h"
-int GTextReadStream::get_next_toc_type() const
+enum Gis_read_stream::enum_tok_types Gis_read_stream::get_next_toc_type()
{
- const char *cur = m_cur;
- while ((*cur)&&(strchr(" \t\r\n",*cur)))
- {
- cur++;
- }
- if (!(*cur))
- {
+ skip_space();
+ if (m_cur >= m_limit)
return eostream;
- }
-
- if (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
- (*cur=='_'))
- {
+ if (my_isvar_start(&my_charset_bin, *m_cur))
return word;
- }
-
- if (((*cur>='0') && (*cur<='9')) || (*cur=='-') || (*cur=='+') ||
- (*cur=='.'))
- {
+ if ((*m_cur >= '0' && *m_cur <= '9') || *m_cur == '-' || *m_cur == '+')
return numeric;
- }
-
- if (*cur == '(')
- {
+ if (*m_cur == '(')
return l_bra;
- }
-
- if (*cur == ')')
- {
+ if (*m_cur == ')')
return r_bra;
- }
-
- if (*cur == ',')
- {
+ if (*m_cur == ',')
return comma;
- }
-
return unknown;
}
-const char *GTextReadStream::get_next_word(int *word_len)
-{
- const char *cur = m_cur;
- while ((*cur)&&(strchr(" \t\r\n",*cur)))
- {
- cur++;
- }
- m_last_text_position = cur;
-
- if (!(*cur))
- {
- return 0;
- }
- const char *wd_start = cur;
-
- if (((*cur<'a') || (*cur>'z')) && ((*cur<'A') || (*cur>'Z')) && (*cur!='_'))
- {
- return NULL;
- }
+bool Gis_read_stream::get_next_word(LEX_STRING *res)
+{
+ skip_space();
+ res->str= (char*) m_cur;
+ /* The following will also test for \0 */
+ if (!my_isvar_start(&my_charset_bin, *m_cur))
+ return 1;
- ++cur;
+ /*
+ We can't combine the following increment with my_isvar() because
+ my_isvar() is a macro that would cause side effects
+ */
+ m_cur++;
+ while ((m_cur < m_limit) && my_isvar(&my_charset_bin, *m_cur))
+ m_cur++;
- while (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
- (*cur=='_') || ((*cur>='0') && (*cur<='9')))
- {
- ++cur;
- }
+ res->length= (uint32) (m_cur - res->str);
+ return 0;
+}
- *word_len = cur - wd_start;
- m_cur = cur;
+/*
+ Read a floating point number
- return wd_start;
-}
+ NOTE: Number must start with a digit or sign. It can't start with a decimal
+ point
+*/
-int GTextReadStream::get_next_number(double *d)
+bool Gis_read_stream::get_next_number(double *d)
{
- const char *cur = m_cur;
- while ((*cur)&&(strchr(" \t\r\n",*cur)))
- {
- cur++;
- }
+ char *endptr;
+ int err;
- m_last_text_position = cur;
- if (!(*cur))
- {
- set_error_msg("Numeric constant expected");
- return 1;
- }
+ skip_space();
- if (((*cur<'0') || (*cur>'9')) && (*cur!='-') && (*cur!='+') && (*cur!='.'))
+ if ((m_cur >= m_limit) ||
+ (*m_cur < '0' || *m_cur > '9') && *m_cur != '-' && *m_cur != '+')
{
set_error_msg("Numeric constant expected");
return 1;
}
- char *endptr;
-
- *d = my_strtod(cur, &endptr);
-
+ *d = my_strntod(m_charset, (char *)m_cur,
+ m_limit-m_cur, &endptr, &err);
+ if (err)
+ return 1;
if (endptr)
- {
m_cur = endptr;
- }
-
return 0;
}
-char GTextReadStream::get_next_symbol()
+
+bool Gis_read_stream::check_next_symbol(char symbol)
{
- const char *cur = m_cur;
- while ((*cur)&&(strchr(" \t\r\n",*cur)))
+ skip_space();
+ if ((m_cur >= m_limit) || (*m_cur != symbol))
{
- cur++;
- }
- if (!(*cur))
- {
- return 0;
+ char buff[32];
+ strmov(buff, "'?' expected");
+ buff[2]= symbol;
+ set_error_msg(buff);
+ return 1;
}
+ m_cur++;
+ return 0;
+}
- m_cur = cur + 1;
- m_last_text_position = cur;
- return *cur;
-}
+/*
+ Remember error message.
+*/
-void GTextReadStream::set_error_msg(const char *msg)
+void Gis_read_stream::set_error_msg(const char *msg)
{
- size_t len = strlen(msg);
- m_err_msg = (char *)my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR));
+ size_t len= strlen(msg); // ok in this context
+ m_err_msg= (char *) my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR));
memcpy(m_err_msg, msg, len + 1);
}
-
-
diff --git a/sql/gstream.h b/sql/gstream.h
index a3914a534dd..bfbf28851ce 100644
--- a/sql/gstream.h
+++ b/sql/gstream.h
@@ -15,10 +15,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-class GTextReadStream
+class Gis_read_stream
{
public:
- enum TokTypes
+ enum enum_tok_types
{
unknown,
eostream,
@@ -29,41 +29,48 @@ public:
comma
};
- GTextReadStream(const char *buffer, int size)
- :m_cur(buffer), m_limit(buffer + size), m_last_text_position(buffer),
- m_err_msg(NULL)
+ Gis_read_stream(CHARSET_INFO *charset, const char *buffer, int size)
+ :m_cur(buffer), m_limit(buffer + size), m_err_msg(NULL), m_charset(charset)
{}
- GTextReadStream(): m_cur(NULL), m_limit(NULL), m_err_msg(NULL)
+ Gis_read_stream(): m_cur(NullS), m_limit(NullS), m_err_msg(NullS)
{}
-
- ~GTextReadStream()
+ ~Gis_read_stream()
{
my_free(m_err_msg, MYF(MY_ALLOW_ZERO_PTR));
}
- int get_next_toc_type() const;
- const char *get_next_word(int *word_len);
- int get_next_number(double *d);
- char get_next_symbol();
+ enum enum_tok_types get_next_toc_type();
+ bool get_next_word(LEX_STRING *);
+ bool get_next_number(double *);
+ bool check_next_symbol(char);
- const char *get_last_text_position() const
+ inline void skip_space()
{
- return m_last_text_position;
+ while ((m_cur < m_limit) && my_isspace(&my_charset_latin1, *m_cur))
+ m_cur++;
+ }
+ /* Skip next character, if match. Return 1 if no match */
+ inline bool skip_char(char skip)
+ {
+ skip_space();
+ if ((m_cur >= m_limit) || *m_cur != skip)
+ return 1; /* Didn't find char */
+ m_cur++;
+ return 0;
}
-
void set_error_msg(const char *msg);
// caller should free this pointer
char *get_error_msg()
{
char *err_msg = m_err_msg;
- m_err_msg = NULL;
+ m_err_msg= NullS;
return err_msg;
}
protected:
const char *m_cur;
const char *m_limit;
- const char *m_last_text_position;
char *m_err_msg;
+ CHARSET_INFO *m_charset;
};
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 0dccab0c9d3..70ecc61bfb8 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -72,7 +72,7 @@
#define STATUS_BDB_ANALYZE 4
const char *ha_berkeley_ext=".db";
-bool berkeley_skip=0,berkeley_shared_data=0;
+bool berkeley_shared_data=0;
u_int32_t berkeley_init_flags= DB_PRIVATE | DB_RECOVER, berkeley_env_flags=0,
berkeley_lock_type=DB_LOCK_DEFAULT;
ulong berkeley_cache_size, berkeley_log_buffer_size, berkeley_log_file_size=0;
@@ -1343,7 +1343,7 @@ int ha_berkeley::index_init(uint keynr)
int ha_berkeley::index_end()
{
int error=0;
- DBUG_ENTER("index_end");
+ DBUG_ENTER("ha_berkely::index_end");
if (cursor)
{
DBUG_PRINT("enter",("table: '%s'", table->real_name));
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index aa0a7daeb43..581b50501e8 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -170,7 +170,7 @@ class ha_berkeley: public handler
uint8 table_cache_type() { return HA_CACHE_TBL_TRANSACT; }
};
-extern bool berkeley_skip, berkeley_shared_data;
+extern bool berkeley_shared_data;
extern u_int32_t berkeley_init_flags,berkeley_env_flags, berkeley_lock_type,
berkeley_lock_types[];
extern ulong berkeley_cache_size, berkeley_max_lock, berkeley_log_buffer_size;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 3d226e42d82..5d3d2a2fb4f 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -80,7 +80,6 @@ extern "C" {
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
#define HA_INNOBASE_RANGE_COUNT 100
-bool innodb_skip = 0;
uint innobase_init_flags = 0;
ulong innobase_cache_size = 0;
@@ -703,7 +702,7 @@ ha_innobase::init_table_handle_for_HANDLER(void)
/* Always fetch all columns in the index record */
- prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
+ prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
/* We want always to fetch all columns in the whole row? Or do
we???? */
@@ -982,19 +981,13 @@ innobase_commit_low(
}
#ifdef HAVE_REPLICATION
- /* TODO: Guilhem should check if master_log_name, pending
- etc. are right if the master log gets rotated! Possible bug here.
- Comment by Heikki March 4, 2003. */
-
if (current_thd->slave_thread) {
/* Update the replication position info inside InnoDB */
trx->mysql_master_log_file_name
= active_mi->rli.group_master_log_name;
- trx->mysql_master_log_pos = ((ib_longlong)
- (active_mi->rli.group_master_log_pos +
- active_mi->rli.event_len
- ));
+ trx->mysql_master_log_pos= ((ib_longlong)
+ active_mi->rli.future_group_master_log_pos);
}
#endif /* HAVE_REPLICATION */
@@ -1952,6 +1945,7 @@ build_template(
ulint n_fields;
ulint n_requested_fields = 0;
ibool fetch_all_in_key = FALSE;
+ ibool fetch_primary_key_cols = FALSE;
ulint i;
if (prebuilt->select_lock_type == LOCK_X) {
@@ -1962,8 +1956,9 @@ build_template(
templ_type = ROW_MYSQL_WHOLE_ROW;
}
- if (templ_type == ROW_MYSQL_REC_FIELDS
- && !prebuilt->hint_no_need_to_fetch_extra_cols) {
+ if (templ_type == ROW_MYSQL_REC_FIELDS) {
+ if (prebuilt->hint_need_to_fetch_extra_cols
+ == ROW_RETRIEVE_ALL_COLS) {
/* We know we must at least fetch all columns in the key, or
all columns in the table */
@@ -1978,15 +1973,18 @@ build_template(
fetch_all_in_key = TRUE;
} else {
- /* We are building a temporary table: fetch all
- columns; the reason is that MySQL may use the
- clustered index key to store rows, but the mechanism
- we use below to detect required columns does not
- reveal that. Actually, it might be enough to
- fetch only all in the key also in this case! */
-
templ_type = ROW_MYSQL_WHOLE_ROW;
}
+ } else if (prebuilt->hint_need_to_fetch_extra_cols
+ == ROW_RETRIEVE_PRIMARY_KEY) {
+ /* We must at least fetch all primary key cols. Note that if
+ the clustered index was internally generated by InnoDB on the
+ row id (no primary key was defined), then
+ row_search_for_mysql() will always retrieve the row id to a
+ special buffer in the prebuilt struct. */
+
+ fetch_primary_key_cols = TRUE;
+ }
}
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
@@ -2005,7 +2003,7 @@ build_template(
the clustered index */
}
- n_fields = (ulint)table->fields;
+ n_fields = (ulint)table->fields; /* number of columns */
if (!prebuilt->mysql_template) {
prebuilt->mysql_template = (mysql_row_templ_t*)
@@ -2018,6 +2016,8 @@ build_template(
prebuilt->templ_contains_blob = FALSE;
+ /* Note that in InnoDB, i is the column number. MySQL calls columns
+ 'fields'. */
for (i = 0; i < n_fields; i++) {
templ = prebuilt->mysql_template + n_requested_fields;
field = table->field[i];
@@ -2030,6 +2030,8 @@ build_template(
if (templ_type == ROW_MYSQL_REC_FIELDS
&& !(fetch_all_in_key
&& dict_index_contains_col_or_prefix(index, i))
+ && !(fetch_primary_key_cols
+ && dict_table_col_in_clustered_key(index->table, i))
&& thd->query_id != field->query_id) {
/* This field is not needed in the query, skip it */
@@ -2111,8 +2113,27 @@ ha_innobase::write_row(
DBUG_ENTER("ha_innobase::write_row");
- ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ if (prebuilt->trx !=
+ (trx_t*) current_thd->transaction.all.innobase_tid) {
+ char err_buf[2000];
+
+ fprintf(stderr,
+"InnoDB: Error: the transaction object for the table handle is at\n"
+"InnoDB: %lx, but for the current thread it is at %lx\n",
+ (ulong)prebuilt->trx,
+ (ulong)current_thd->transaction.all.innobase_tid);
+
+ ut_sprintf_buf(err_buf, ((byte*)prebuilt) - 100, 200);
+ fprintf(stderr,
+"InnoDB: Dump of 200 bytes around prebuilt: %.1000s\n", err_buf);
+
+ ut_sprintf_buf(err_buf,
+ ((byte*)(&(current_thd->transaction.all))) - 100, 200);
+ fprintf(stderr,
+"InnoDB: Dump of 200 bytes around transaction.all: %.1000s\n", err_buf);
+
+ ut_a(0);
+ }
statistic_increment(ha_write_count, &LOCK_status);
@@ -4515,7 +4536,14 @@ ha_innobase::extra(
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_RETRIEVE_ALL_COLS:
- prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
+ prebuilt->hint_need_to_fetch_extra_cols
+ = ROW_RETRIEVE_ALL_COLS;
+ break;
+ case HA_EXTRA_RETRIEVE_PRIMARY_KEY:
+ if (prebuilt->hint_need_to_fetch_extra_cols == 0) {
+ prebuilt->hint_need_to_fetch_extra_cols
+ = ROW_RETRIEVE_PRIMARY_KEY;
+ }
break;
case HA_EXTRA_KEYREAD:
prebuilt->read_just_key = 1;
@@ -4576,7 +4604,7 @@ ha_innobase::start_stmt(
auto_inc_counter_for_this_stat = 0;
prebuilt->sql_stat_start = TRUE;
- prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
+ prebuilt->hint_need_to_fetch_extra_cols = 0;
prebuilt->read_just_key = 0;
if (!prebuilt->mysql_has_locked) {
@@ -4653,7 +4681,7 @@ ha_innobase::external_lock(
trx = prebuilt->trx;
prebuilt->sql_stat_start = TRUE;
- prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
+ prebuilt->hint_need_to_fetch_extra_cols = 0;
prebuilt->read_just_key = 0;
@@ -4758,7 +4786,7 @@ innodb_show_status(
DBUG_ENTER("innodb_show_status");
- if (innodb_skip) {
+ if (have_innodb != SHOW_OPTION_YES) {
my_message(ER_NOT_SUPPORTED_YET,
"Cannot call SHOW INNODB STATUS because skip-innodb is defined",
MYF(0));
@@ -4997,7 +5025,7 @@ ha_innobase::innobase_read_and_init_auto_inc(
/* Play safe and also give in another way the hint to fetch
all columns in the key: */
- prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
+ prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
prebuilt->trx->mysql_n_tables_locked += 1;
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 229ca514eda..4efde3e95d2 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -190,7 +190,6 @@ class ha_innobase: public handler
uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; }
};
-extern bool innodb_skip;
extern uint innobase_init_flags, innobase_lock_type;
extern uint innobase_flush_log_at_trx_commit;
extern ulong innobase_cache_size;
diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc
index 1763427e8d9..299d6caaf43 100644
--- a/sql/ha_isam.cc
+++ b/sql/ha_isam.cc
@@ -34,7 +34,6 @@
** isam tables
*****************************************************************************/
-bool isam_skip;
const char **ha_isam::bas_ext() const
{ static const char *ext[]= { ".ISM",".ISD", NullS }; return ext; }
diff --git a/sql/ha_isam.h b/sql/ha_isam.h
index 0b8619e5f33..129777e68e5 100644
--- a/sql/ha_isam.h
+++ b/sql/ha_isam.h
@@ -82,4 +82,3 @@ class ha_isam: public handler
enum thr_lock_type lock_type);
};
-extern bool isam_skip;
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index a87054333cb..a2a5f040081 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -1362,6 +1362,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
create_info.data_file_name= info->data_file_name;
create_info.index_file_name=info->index_file_name;
+ /* TODO: Check that the following fn_format is really needed */
error=mi_create(fn_format(buff,name,"","",2+4),
table_arg->keys,keydef,
(uint) (recinfo_pos-recinfo), recinfo,
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index ddffcfecc29..4d66639690d 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -37,7 +37,7 @@ extern ulong myisam_recover_options;
class ha_myisam: public handler
{
MI_INFO *file;
- uint int_table_flags;
+ ulong int_table_flags;
char *data_file_name, *index_file_name;
bool enable_activate_all_index;
int repair(THD *thd, MI_CHECK &param, bool optimize);
diff --git a/sql/handler.cc b/sql/handler.cc
index 5aa3967edb6..8a4a6005d85 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -120,34 +120,21 @@ const char *ha_get_storage_engine(enum db_type db_type)
enum db_type ha_checktype(enum db_type database_type)
{
+ show_table_type_st *types;
+ for (types= sys_table_types; types->type; types++)
+ {
+ if ((database_type == types->db_type) &&
+ (*types->value == SHOW_OPTION_YES))
+ return database_type;
+ }
+
switch (database_type) {
-#ifdef HAVE_BERKELEY_DB
- case DB_TYPE_BERKELEY_DB:
- if (berkeley_skip) break;
- return (database_type);
-#endif
-#ifdef HAVE_INNOBASE_DB
- case DB_TYPE_INNODB:
- if (innodb_skip) break;
- return (database_type);
-#endif
#ifndef NO_HASH
case DB_TYPE_HASH:
-#endif
-#ifdef HAVE_ISAM
- case DB_TYPE_ISAM:
- if (isam_skip) break;
return (database_type);
- case DB_TYPE_MRG_ISAM:
- return (isam_skip ? DB_TYPE_MRG_MYISAM : database_type);
-#else
+#endif
case DB_TYPE_MRG_ISAM:
return (DB_TYPE_MRG_MYISAM);
-#endif
- case DB_TYPE_HEAP:
- case DB_TYPE_MYISAM:
- case DB_TYPE_MRG_MYISAM:
- return (database_type); /* Database exists on system */
default:
break;
}
@@ -165,7 +152,8 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
{
switch (db_type) {
#ifndef NO_HASH
- return new ha_hash(table);
+ case DB_TYPE_HASH:
+ return new ha_hash(table);
#endif
#ifdef HAVE_ISAM
case DB_TYPE_MRG_ISAM:
@@ -203,30 +191,32 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
int ha_init()
{
+ int error= 0;
#ifdef HAVE_BERKELEY_DB
- if (!berkeley_skip)
+ if (have_berkeley_db == SHOW_OPTION_YES)
{
- int error;
- if ((error=berkeley_init()))
- return error;
- if (!berkeley_skip) // If we couldn't use handler
- opt_using_transactions=1;
+ if (berkeley_init())
+ {
+ have_berkeley_db= SHOW_OPTION_DISABLED; // If we couldn't use handler
+ error= 1;
+ }
else
- have_berkeley_db=SHOW_OPTION_DISABLED;
+ opt_using_transactions=1;
}
#endif
#ifdef HAVE_INNOBASE_DB
- if (!innodb_skip)
+ if (have_innodb == SHOW_OPTION_YES)
{
if (innobase_init())
- return -1;
- if (!innodb_skip) // If we couldn't use handler
- opt_using_transactions=1;
+ {
+ have_innodb= SHOW_OPTION_DISABLED; // If we couldn't use handler
+ error= 1;
+ }
else
- have_innodb=SHOW_OPTION_DISABLED;
+ opt_using_transactions=1;
}
#endif
- return 0;
+ return error;
}
/* close, flush or restart databases */
@@ -246,11 +236,11 @@ int ha_panic(enum ha_panic_function flag)
error|=mi_panic(flag);
error|=myrg_panic(flag);
#ifdef HAVE_BERKELEY_DB
- if (!berkeley_skip)
+ if (have_berkeley_db == SHOW_OPTION_YES)
error|=berkeley_end();
#endif
#ifdef HAVE_INNOBASE_DB
- if (!innodb_skip)
+ if (have_innodb == SHOW_OPTION_YES)
error|=innobase_end();
#endif
return error;
@@ -259,7 +249,7 @@ int ha_panic(enum ha_panic_function flag)
void ha_drop_database(char* path)
{
#ifdef HAVE_INNOBASE_DB
- if (!innodb_skip)
+ if (have_innodb == SHOW_OPTION_YES)
innobase_drop_database(path);
#endif
}
@@ -267,7 +257,7 @@ void ha_drop_database(char* path)
void ha_close_connection(THD* thd)
{
#ifdef HAVE_INNOBASE_DB
- if (!innodb_skip)
+ if (have_innodb == SHOW_OPTION_YES)
innobase_close_connection(thd);
#endif
}
@@ -632,11 +622,13 @@ bool ha_flush_logs()
{
bool result=0;
#ifdef HAVE_BERKELEY_DB
- if (!berkeley_skip && berkeley_flush_logs())
+ if ((have_berkeley_db == SHOW_OPTION_YES) &&
+ berkeley_flush_logs())
result=1;
#endif
#ifdef HAVE_INNOBASE_DB
- if (!innodb_skip && innobase_flush_logs())
+ if ((have_innodb == SHOW_OPTION_YES) &&
+ innobase_flush_logs())
result=1;
#endif
return result;
diff --git a/sql/item.cc b/sql/item.cc
index 5aaeffff5d2..7549bac71b8 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -103,21 +103,33 @@ void Item::print_item_w_name(String *str)
Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par)
- :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par),
+ :changed_during_fix_field(0), db_name(db_name_par),
+ table_name(table_name_par), field_name(field_name_par),
depended_from(0)
{
name = (char*) field_name_par;
}
// Constructor used by Item_field & Item_ref (see Item comment)
-Item_ident::Item_ident(THD *thd, Item_ident *item):
- Item(thd, item),
- db_name(item->db_name),
- table_name(item->table_name),
- field_name(item->field_name),
- depended_from(item->depended_from)
+Item_ident::Item_ident(THD *thd, Item_ident *item)
+ :Item(thd, item),
+ changed_during_fix_field(0),
+ db_name(item->db_name),
+ table_name(item->table_name),
+ field_name(item->field_name),
+ depended_from(item->depended_from)
{}
+void Item_ident::cleanup()
+{
+ Item::cleanup();
+ if (changed_during_fix_field)
+ {
+ *changed_during_fix_field= this;
+ changed_during_fix_field= 0;
+ }
+}
+
bool Item_ident::remove_dependence_processor(byte * arg)
{
DBUG_ENTER("Item_ident::remove_dependence_processor");
@@ -289,11 +301,12 @@ bool DTCollation::aggregate(DTCollation &dt)
return 0;
}
-Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
+Item_field::Item_field(Field *f)
+ :Item_ident(NullS, f->table_name, f->field_name)
{
set_field(f);
collation.set(DERIVATION_IMPLICIT);
- fixed= 1; // This item is not needed in fix_fields
+ fixed= 1;
}
// Constructor need to process subselect with temporary tables (see Item)
@@ -341,6 +354,7 @@ const char *Item_ident::full_name() const
/* ARGSUSED */
String *Item_field::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if ((null_value=field->is_null()))
return 0;
str->set_charset(str_value.charset());
@@ -349,6 +363,7 @@ String *Item_field::val_str(String *str)
double Item_field::val()
{
+ DBUG_ASSERT(fixed == 1);
if ((null_value=field->is_null()))
return 0.0;
return field->val_real();
@@ -356,6 +371,7 @@ double Item_field::val()
longlong Item_field::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if ((null_value=field->is_null()))
return 0;
return field->val_int();
@@ -440,9 +456,8 @@ bool Item_field::eq(const Item *item, bool binary_cmp) const
(!my_strcasecmp(table_alias_charset, item_field->table_name,
table_name) &&
(!item_field->db_name ||
- (item_field->db_name && !my_strcasecmp(table_alias_charset,
- item_field->db_name,
- db_name))))));
+ (item_field->db_name && !strcmp(item_field->db_name,
+ db_name))))));
}
@@ -465,6 +480,8 @@ Item *Item_field::get_tmp_table_item(THD *thd)
String *Item_int::val_str(String *str)
{
+ // following assert is redundant, because fixed=1 assigned in constructor
+ DBUG_ASSERT(fixed == 1);
str->set(value, &my_charset_bin);
return str;
}
@@ -479,6 +496,8 @@ void Item_int::print(String *str)
String *Item_uint::val_str(String *str)
{
+ // following assert is redundant, because fixed=1 assigned in constructor
+ DBUG_ASSERT(fixed == 1);
str->set((ulonglong) value, &my_charset_bin);
return str;
}
@@ -494,6 +513,8 @@ void Item_uint::print(String *str)
String *Item_real::val_str(String *str)
{
+ // following assert is redundant, because fixed=1 assigned in constructor
+ DBUG_ASSERT(fixed == 1);
str->set(value,decimals,&my_charset_bin);
return str;
}
@@ -510,14 +531,57 @@ void Item_string::print(String *str)
bool Item_null::eq(const Item *item, bool binary_cmp) const
{ return item->type() == type(); }
-double Item_null::val() { null_value=1; return 0.0; }
-longlong Item_null::val_int() { null_value=1; return 0; }
+double Item_null::val()
+{
+ // following assert is redundant, because fixed=1 assigned in constructor
+ DBUG_ASSERT(fixed == 1);
+ null_value=1;
+ return 0.0;
+}
+longlong Item_null::val_int()
+{
+ // following assert is redundant, because fixed=1 assigned in constructor
+ DBUG_ASSERT(fixed == 1);
+ null_value=1;
+ return 0;
+}
/* ARGSUSED */
String *Item_null::val_str(String *str)
-{ null_value=1; return 0;}
+{
+ // following assert is redundant, because fixed=1 assigned in constructor
+ DBUG_ASSERT(fixed == 1);
+ null_value=1;
+ return 0;
+}
+
+
+/*********************** Item_param related ******************************/
+
+/*
+ Default function of Item_param::set_param_func, so in case
+ of malformed packet the server won't SIGSEGV
+*/
+
+static void
+default_set_param_func(Item_param *param,
+ uchar **pos __attribute__((unused)),
+ ulong len __attribute__((unused)))
+{
+ param->set_null();
+}
+Item_param::Item_param(unsigned position) :
+ value_is_set(FALSE),
+ item_result_type(STRING_RESULT),
+ item_type(STRING_ITEM),
+ item_is_time(FALSE),
+ long_data_supplied(FALSE),
+ pos_in_query(position),
+ set_param_func(default_set_param_func)
+{
+ name= (char*) "?";
+}
-/* Item_param related */
void Item_param::set_null()
{
DBUG_ENTER("Item_param::set_null");
@@ -613,7 +677,7 @@ int Item_param::save_in_field(Field *field, bool no_conversions)
return 0;
}
String *result=val_str(&str_value);
- return (field->store(result->ptr(),result->length(),field->charset())) ? -1 : 0;
+ return field->store(result->ptr(),result->length(),field->charset());
}
bool Item_param::get_time(TIME *res)
@@ -624,6 +688,7 @@ bool Item_param::get_time(TIME *res)
double Item_param::val()
{
+ DBUG_ASSERT(fixed == 1);
int err;
switch (item_result_type) {
case STRING_RESULT:
@@ -639,8 +704,9 @@ double Item_param::val()
longlong Item_param::val_int()
{
- int err;
- switch (item_result_type) {
+ DBUG_ASSERT(fixed == 1);
+ int err;
+ switch (item_result_type) {
case STRING_RESULT:
return my_strntoll(str_value.charset(),
str_value.ptr(),str_value.length(),10,
@@ -655,6 +721,7 @@ longlong Item_param::val_int()
String *Item_param::val_str(String* str)
{
+ DBUG_ASSERT(fixed == 1);
switch (item_result_type) {
case INT_RESULT:
str->set(int_value, &my_charset_bin);
@@ -673,7 +740,8 @@ String *Item_param::val_str(String* str)
*/
String *Item_param::query_val_str(String* str)
-{
+{
+ DBUG_ASSERT(fixed == 1);
switch (item_result_type) {
case INT_RESULT:
case REAL_RESULT:
@@ -746,6 +814,7 @@ void Item_copy_string::copy()
/* ARGSUSED */
String *Item_copy_string::val_str(String *str)
{
+ // Item_copy_string is used without fix_fields call
if (null_value)
return (String*) 0;
return &str_value;
@@ -760,28 +829,40 @@ bool Item::fix_fields(THD *thd,
struct st_table_list *list,
Item ** ref)
{
+
+ // We do not check fields which are fixed during construction
+ DBUG_ASSERT(fixed == 0 || basic_const_item());
fixed= 1;
return 0;
}
double Item_ref_null_helper::val()
{
+ DBUG_ASSERT(fixed == 1);
double tmp= (*ref)->val_result();
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
+
+
longlong Item_ref_null_helper::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong tmp= (*ref)->val_int_result();
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
+
+
String* Item_ref_null_helper::val_str(String* s)
{
+ DBUG_ASSERT(fixed == 1);
String* tmp= (*ref)->str_result(s);
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
+
+
bool Item_ref_null_helper::get_date(TIME *ltime, uint fuzzydate)
{
return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate));
@@ -821,6 +902,7 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
if (!field) // If field is not checked
{
TABLE_LIST *where= 0;
@@ -926,8 +1008,13 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
ref,
(char *)table_name,
(char *)field_name);
+ register_item_tree_changing(ref);
if (!rf)
return 1;
+ /*
+ rf is Item_ref => never substitute other items (in this case)
+ during fix_fields() => we can use rf after fix_fields()
+ */
if (rf->fix_fields(thd, tables, ref) || rf->check_cols(1))
return 1;
@@ -946,6 +1033,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(char *)field_name);
if (!rf)
return 1;
+ /*
+ rf is Item_ref => never substitute other items (in this case)
+ during fix_fields() => we can use rf after fix_fields()
+ */
return rf->fix_fields(thd, tables, ref) || rf->check_cols(1);
}
}
@@ -971,6 +1062,11 @@ void Item_field::cleanup()
{
DBUG_ENTER("Item_field::cleanup");
Item_ident::cleanup();
+ /*
+ Even if this object was created by direct link to field in setup_wild()
+ it will be linked correctly next tyme by name of field and table alias.
+ I.e. we can drop 'field'.
+ */
field= result_field= 0;
DBUG_VOID_RETURN;
}
@@ -1210,7 +1306,7 @@ int Item::save_in_field(Field *field, bool no_conversions)
field->set_notnull();
error=field->store(nr);
}
- return (error) ? -1 : 0;
+ return error;
}
@@ -1221,8 +1317,7 @@ int Item_string::save_in_field(Field *field, bool no_conversions)
if (null_value)
return set_field_to_null(field);
field->set_notnull();
- return (field->store(result->ptr(),result->length(),collation.collation)) ?
- -1 : 0;
+ return field->store(result->ptr(),result->length(),collation.collation);
}
int Item_uint::save_in_field(Field *field, bool no_conversions)
@@ -1241,9 +1336,13 @@ int Item_int::save_in_field(Field *field, bool no_conversions)
if (null_value)
return set_field_to_null(field);
field->set_notnull();
- return (field->store(nr)) ? -1 : 0;
+ return field->store(nr);
}
+Item_num *Item_uint::neg()
+{
+ return new Item_real(name, - ((double) value), 0, max_length);
+}
int Item_real::save_in_field(Field *field, bool no_conversions)
{
@@ -1251,7 +1350,7 @@ int Item_real::save_in_field(Field *field, bool no_conversions)
if (null_value)
return set_field_to_null(field);
field->set_notnull();
- return (field->store(nr)) ? -1 : 0;
+ return field->store(nr);
}
/****************************************************************************
@@ -1286,10 +1385,13 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length)
}
*ptr=0; // Keep purify happy
collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
+ fixed= 1;
}
longlong Item_varbinary::val_int()
{
+ // following assert is redundant, because fixed=1 assigned in constructor
+ DBUG_ASSERT(fixed == 1);
char *end=(char*) str_value.ptr()+str_value.length(),
*ptr=end-min(str_value.length(),sizeof(longlong));
@@ -1313,7 +1415,7 @@ int Item_varbinary::save_in_field(Field *field, bool no_conversions)
longlong nr=val_int();
error=field->store(nr);
}
- return (error) ? -1 : 0;
+ return error;
}
@@ -1446,6 +1548,7 @@ bool Item_field::send(Protocol *protocol, String *buffer)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
+ DBUG_ASSERT(fixed == 0);
uint counter;
if (!ref)
{
@@ -1551,6 +1654,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
Item_field* fld;
if (!((*reference)= fld= new Item_field(tmp)))
return 1;
+ register_item_tree_changing(reference);
mark_as_dependent(thd, last, thd->lex->current_select, fld);
return 0;
}
@@ -1658,16 +1762,19 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const
}
-bool Item_default_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items)
+bool Item_default_value::fix_fields(THD *thd,
+ struct st_table_list *table_list,
+ Item **items)
{
+ DBUG_ASSERT(fixed == 0);
if (!arg)
- return false;
- bool res= arg->fix_fields(thd, table_list, items);
- if (res)
- return res;
- /* arg->type() can be only REF_ITEM or FIELD_ITEM for it defined as
- simple_ident in sql_yacc.yy
- */
+ {
+ fixed= 1;
+ return 0;
+ }
+ if (arg->fix_fields(thd, table_list, &arg))
+ return 1;
+
if (arg->type() == REF_ITEM)
{
Item_ref *ref= (Item_ref *)arg;
@@ -1685,6 +1792,7 @@ bool Item_default_value::fix_fields(THD *thd, struct st_table_list *table_list,
def_field->move_field(def_field->table->default_values -
def_field->table->record[0]);
set_field(def_field);
+ fixed= 1;
return 0;
}
@@ -1711,13 +1819,10 @@ bool Item_insert_value::fix_fields(THD *thd,
struct st_table_list *table_list,
Item **items)
{
- bool res= arg->fix_fields(thd, table_list, items);
- if (res)
- return res;
- /*
- arg->type() can be only REF_ITEM or FIELD_ITEM as arg is
- a simple_ident in sql_yacc.yy
- */
+ DBUG_ASSERT(fixed == 0);
+ if (arg->fix_fields(thd, table_list, &arg))
+ return 1;
+
if (arg->type() == REF_ITEM)
{
Item_ref *ref= (Item_ref *)arg;
@@ -1745,6 +1850,7 @@ bool Item_insert_value::fix_fields(THD *thd,
set_field(new Field_null(0, 0, Field::NONE, tmp_field->field_name,
tmp_field->table, &my_charset_bin));
}
+ fixed= 1;
return 0;
}
@@ -1908,7 +2014,8 @@ void Item_cache_str::store(Item *item)
double Item_cache_str::val()
-{
+{
+ DBUG_ASSERT(fixed == 1);
int err;
if (value)
return my_strntod(value->charset(), (char*) value->ptr(),
@@ -1920,6 +2027,7 @@ double Item_cache_str::val()
longlong Item_cache_str::val_int()
{
+ DBUG_ASSERT(fixed == 1);
int err;
if (value)
return my_strntoll(value->charset(), value->ptr(),
diff --git a/sql/item.h b/sql/item.h
index fb93e0ef8ab..5f94320b547 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -137,6 +137,11 @@ public:
}
virtual void make_field(Send_field *field);
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
+ /*
+ should be used in case where we are shure that we do not need
+ complete fix_fields() procedure.
+ */
+ inline void quick_fix_field() { fixed= 1; }
virtual int save_in_field(Field *field, bool no_conversions);
virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field, 1); }
@@ -233,7 +238,7 @@ public:
Field *tmp_table_field_from_field_type(TABLE *table);
/* Used in sql_select.cc:eliminate_not_funcs() */
- virtual Item *neg_transformer() { return NULL; }
+ virtual Item *neg_transformer(THD *thd) { return NULL; }
void delete_self()
{
cleanup();
@@ -242,9 +247,17 @@ public:
};
+class Item_num: public Item
+{
+public:
+ virtual Item_num* neg()= 0;
+};
+
+
class st_select_lex;
class Item_ident :public Item
{
+ Item **changed_during_fix_field;
public:
const char *db_name;
const char *table_name;
@@ -254,7 +267,9 @@ public:
const char *field_name_par);
Item_ident(THD *thd, Item_ident *item);
const char *full_name() const;
-
+ void cleanup();
+ void register_item_tree_changing(Item **ref)
+ { changed_during_fix_field= ref; }
bool remove_dependence_processor(byte * arg);
};
@@ -264,11 +279,17 @@ class Item_field :public Item_ident
void set_field(Field *field);
public:
Field *field,*result_field;
- // Item_field() {}
+#ifndef DBUG_OFF
+ bool double_fix;
+#endif
Item_field(const char *db_par,const char *table_name_par,
const char *field_name_par)
- :Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0)
+ :Item_ident(db_par,table_name_par,field_name_par),
+ field(0), result_field(0)
+#ifndef DBUG_OFF
+ ,double_fix(0)
+#endif
{ collation.set(DERIVATION_IMPLICIT); }
// Constructor need to process subselect with temporary tables (see Item)
Item_field(THD *thd, Item_field *item);
@@ -305,13 +326,19 @@ public:
void cleanup();
friend class Item_default_value;
friend class Item_insert_value;
+ friend class st_select_lex_unit;
};
class Item_null :public Item
{
public:
Item_null(char *name_par=0)
- { maybe_null=null_value=TRUE; name= name_par ? name_par : (char*) "NULL";}
+ {
+ maybe_null= null_value= TRUE;
+ max_length= 0;
+ name= name_par ? name_par : (char*) "NULL";
+ fixed= 1;
+ }
enum Type type() const { return NULL_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
double val();
@@ -322,12 +349,8 @@ public:
bool send(Protocol *protocol, String *str);
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
- bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
- {
- bool res= Item::fix_fields(thd, list, item);
- max_length=0;
- return res;
- }
+ // to prevent drop fixed flag (no need parent cleanup call)
+ void cleanup() {}
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; }
@@ -348,16 +371,7 @@ public:
bool long_data_supplied;
uint pos_in_query;
- Item_param(uint position)
- {
- name= (char*) "?";
- pos_in_query= position;
- item_type= STRING_ITEM;
- item_result_type = STRING_RESULT;
- item_is_time= false;
- long_data_supplied= false;
- value_is_set= 0;
- }
+ Item_param(uint position);
enum Type type() const { return item_type; }
double val();
longlong val_int();
@@ -374,11 +388,14 @@ public:
void set_time(TIME *tm, timestamp_type type);
bool get_time(TIME *tm);
void reset() {}
-#ifndef EMBEDDED_LIBRARY
- void (*setup_param_func)(Item_param *param, uchar **pos);
-#else
- void (*setup_param_func)(Item_param *param, uchar **pos, ulong data_len);
-#endif
+ /*
+ Assign placeholder value from bind data.
+ Note, that 'len' has different semantics in embedded library (as we
+ don't need to check that packet is not broken there). See
+ sql_prepare.cc for details.
+ */
+ void (*set_param_func)(Item_param *param, uchar **pos, ulong len);
+
enum Item_result result_type () const
{ return item_result_type; }
String *query_val_str(String *str);
@@ -394,10 +411,10 @@ public:
void print(String *str) { str->append('?'); }
};
-class Item_int :public Item
+class Item_int :public Item_num
{
public:
- const longlong value;
+ longlong value;
Item_int(int32 i,uint length=11) :value((longlong) i)
{ max_length=length; fixed= 1; }
#ifdef HAVE_LONG_LONG
@@ -413,14 +430,16 @@ public:
enum Type type() const { return INT_ITEM; }
enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
- longlong val_int() { return value; }
- double val() { return (double) value; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
String *val_str(String*);
int save_in_field(Field *field, bool no_conversions);
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_int(name,value,max_length); }
- void cleanup() { fixed= 1; } // to prevent drop fixed flag
+ // to prevent drop fixed flag (no need parent cleanup call)
+ void cleanup() {}
void print(String *str);
+ Item_num *neg() { value= -value; return this; }
};
@@ -428,32 +447,31 @@ class Item_uint :public Item_int
{
public:
Item_uint(const char *str_arg, uint length) :
- Item_int(str_arg, (longlong) strtoull(str_arg,(char**) 0,10), length) {}
- Item_uint(uint32 i) :Item_int((longlong) i, 10) {}
- double val() { return ulonglong2double((ulonglong)value); }
+ Item_int(str_arg, (longlong) strtoull(str_arg, (char**) 0,10), length)
+ { unsigned_flag= 1; }
+ Item_uint(uint32 i) :Item_int((longlong) i, 10)
+ { unsigned_flag= 1; }
+ double val()
+ { DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); }
String *val_str(String*);
Item *new_item() { return new Item_uint(name,max_length); }
int save_in_field(Field *field, bool no_conversions);
- bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
- {
- bool res= Item::fix_fields(thd, list, item);
- unsigned_flag= 1;
- return res;
- }
void print(String *str);
+ Item_num *neg ();
};
-class Item_real :public Item
+class Item_real :public Item_num
{
public:
- const double value;
+ double value;
// Item_real() :value(0) {}
- Item_real(const char *str_arg,uint length) :value(my_atof(str_arg))
+ Item_real(const char *str_arg, uint length) :value(my_atof(str_arg))
{
name=(char*) str_arg;
decimals=(uint8) nr_of_decimals(str_arg);
max_length=length;
+ fixed= 1;
}
Item_real(const char *str,double val_arg,uint decimal_par,uint length)
:value(val_arg)
@@ -461,16 +479,24 @@ public:
name=(char*) str;
decimals=(uint8) decimal_par;
max_length=length;
+ fixed= 1;
}
- Item_real(double value_par) :value(value_par) {}
+ Item_real(double value_par) :value(value_par) { fixed= 1; }
int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
- double val() { return value; }
- longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));}
+ double val() { DBUG_ASSERT(fixed == 1); return value; }
+ longlong val_int()
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (longlong) (value+(value > 0 ? 0.5 : -0.5));
+ }
String *val_str(String*);
bool basic_const_item() const { return 1; }
+ // to prevent drop fixed flag (no need parent cleanup call)
+ void cleanup() {}
Item *new_item() { return new Item_real(name,value,decimals,max_length); }
+ Item_num *neg() { value= -value; return this; }
};
@@ -502,6 +528,8 @@ public:
max_length= str_value.numchars()*cs->mbmaxlen;
set_name(str, length, cs);
decimals=NOT_FIXED_DEC;
+ // it is constant => can be used without fix_fields (and frequently used)
+ fixed= 1;
}
Item_string(const char *name_par, const char *str, uint length,
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
@@ -511,21 +539,29 @@ public:
max_length= str_value.numchars()*cs->mbmaxlen;
set_name(name_par,0,cs);
decimals=NOT_FIXED_DEC;
+ // it is constant => can be used without fix_fields (and frequently used)
+ fixed= 1;
}
enum Type type() const { return STRING_ITEM; }
double val()
- {
+ {
+ DBUG_ASSERT(fixed == 1);
int err;
return my_strntod(str_value.charset(), (char*) str_value.ptr(),
str_value.length(), (char**) 0, &err);
}
longlong val_int()
{
+ DBUG_ASSERT(fixed == 1);
int err;
return my_strntoll(str_value.charset(), str_value.ptr(),
str_value.length(), 10, (char**) 0, &err);
}
- String *val_str(String*) { return (String*) &str_value; }
+ String *val_str(String*)
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (String*) &str_value;
+ }
int save_in_field(Field *field, bool no_conversions);
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
@@ -533,11 +569,14 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
Item *new_item()
{
- return new Item_string(name, str_value.ptr(), max_length, &my_charset_bin);
+ return new Item_string(name, str_value.ptr(),
+ str_value.length(), &my_charset_bin);
}
String *const_string() { return &str_value; }
inline void append(char *str, uint length) { str_value.append(str, length); }
void print(String *str);
+ // to prevent drop fixed flag (no need parent cleanup call)
+ void cleanup() {}
};
/* for show tables */
@@ -579,12 +618,16 @@ class Item_varbinary :public Item
public:
Item_varbinary(const char *str,uint str_length);
enum Type type() const { return VARBIN_ITEM; }
- double val() { return (double) Item_varbinary::val_int(); }
+ double val()
+ { DBUG_ASSERT(fixed == 1); return (double) Item_varbinary::val_int(); }
longlong val_int();
- String *val_str(String*) { return &str_value; }
+ bool basic_const_item() const { return 1; }
+ String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; }
int save_in_field(Field *field, bool no_conversions);
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ // to prevent drop fixed flag (no need parent cleanup call)
+ void cleanup() {}
};
@@ -842,7 +885,6 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
bool fix_fields(THD *, struct st_table_list *, Item **);
void print(String *str);
- virtual bool basic_const_item() const { return true; }
int save_in_field(Field *field_arg, bool no_conversions)
{
if (!arg)
@@ -870,7 +912,6 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
bool fix_fields(THD *, struct st_table_list *, Item **);
void print(String *str);
- virtual bool basic_const_item() const { return true; }
int save_in_field(Field *field_arg, bool no_conversions)
{
return Item_field::save_in_field(field_arg, no_conversions);
@@ -894,7 +935,7 @@ public:
void set_used_tables(table_map map) { used_table_map= map; }
- virtual bool allocate(uint i) { return 0; };
+ virtual bool allocate(uint i) { return 0; }
virtual bool setup(Item *item)
{
example= item;
@@ -908,7 +949,8 @@ public:
static Item_cache* get_cache(Item_result type);
table_map used_tables() const { return used_table_map; }
virtual void keep_array() {}
- void cleanup() { fixed= 1; } // to prevent drop fixed flag
+ // to prevent drop fixed flag (no need parent cleanup call)
+ void cleanup() {}
void print(String *str);
};
@@ -919,9 +961,14 @@ public:
Item_cache_int(): Item_cache() {}
void store(Item *item);
- double val() { return (double) value; }
- longlong val_int() { return value; }
- String* val_str(String *str) { str->set(value, default_charset()); return str; }
+ double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ String* val_str(String *str)
+ {
+ DBUG_ASSERT(fixed == 1);
+ str->set(value, default_charset());
+ return str;
+ }
enum Item_result result_type() const { return INT_RESULT; }
};
@@ -932,8 +979,12 @@ public:
Item_cache_real(): Item_cache() {}
void store(Item *item);
- double val() { return value; }
- longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
+ double val() { DBUG_ASSERT(fixed == 1); return value; }
+ longlong val_int()
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (longlong) (value+(value > 0 ? 0.5 : -0.5));
+ }
String* val_str(String *str)
{
str->set(value, decimals, default_charset());
@@ -952,7 +1003,7 @@ public:
void store(Item *item);
double val();
longlong val_int();
- String* val_str(String *) { return value; }
+ String* val_str(String *) { DBUG_ASSERT(fixed == 1); return value; }
enum Item_result result_type() const { return STRING_RESULT; }
CHARSET_INFO *charset() const { return value->charset(); };
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index f0bc73e9501..8f55467a23e 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -103,6 +103,7 @@ Item_bool_func2* Le_creator::create(Item *a, Item *b) const
longlong Item_func_not::val_int()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
null_value=args[0]->null_value;
return !null_value && value == 0 ? 1 : 0;
@@ -113,7 +114,8 @@ longlong Item_func_not::val_int()
*/
longlong Item_func_not_all::val_int()
-{
+{
+ DBUG_ASSERT(fixed == 1);
double value= args[0]->val();
if (abort_on_null)
{
@@ -225,6 +227,13 @@ void Item_bool_func2::fix_length_and_dec()
}
// Make a special case of compare with fields to get nicer DATE comparisons
+
+ if (functype() == LIKE_FUNC) // Disable conversion in case of LIKE function.
+ {
+ set_cmp_func();
+ return;
+ }
+
if (args[0]->type() == FIELD_ITEM)
{
Field *field=((Item_field*) args[0])->field;
@@ -495,7 +504,6 @@ bool Item_in_optimizer::fix_left(THD *thd,
not_null_tables_cache= args[0]->not_null_tables();
with_sum_func= args[0]->with_sum_func;
const_item_cache= args[0]->const_item();
- fixed= 1;
return 0;
}
@@ -503,7 +511,8 @@ bool Item_in_optimizer::fix_left(THD *thd,
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
Item ** ref)
{
- if (fix_left(thd, tables, ref))
+ DBUG_ASSERT(fixed == 0);
+ if (!args[0]->fixed && fix_left(thd, tables, ref))
return 1;
if (args[0]->maybe_null)
maybe_null=1;
@@ -522,12 +531,14 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
used_tables_cache|= args[1]->used_tables();
not_null_tables_cache|= args[1]->not_null_tables();
const_item_cache&= args[1]->const_item();
+ fixed= 1;
return 0;
}
longlong Item_in_optimizer::val_int()
{
+ DBUG_ASSERT(fixed == 1);
cache->store(args[0]);
if (cache->null_value)
{
@@ -566,6 +577,7 @@ bool Item_in_optimizer::is_null()
longlong Item_func_eq::val_int()
{
+ DBUG_ASSERT(fixed == 1);
int value= cmp.compare();
return value == 0 ? 1 : 0;
}
@@ -581,11 +593,13 @@ void Item_func_equal::fix_length_and_dec()
longlong Item_func_equal::val_int()
{
+ DBUG_ASSERT(fixed == 1);
return cmp.compare();
}
longlong Item_func_ne::val_int()
{
+ DBUG_ASSERT(fixed == 1);
int value= cmp.compare();
return value != 0 && !null_value ? 1 : 0;
}
@@ -593,6 +607,7 @@ longlong Item_func_ne::val_int()
longlong Item_func_ge::val_int()
{
+ DBUG_ASSERT(fixed == 1);
int value= cmp.compare();
return value >= 0 ? 1 : 0;
}
@@ -600,12 +615,14 @@ longlong Item_func_ge::val_int()
longlong Item_func_gt::val_int()
{
+ DBUG_ASSERT(fixed == 1);
int value= cmp.compare();
return value > 0 ? 1 : 0;
}
longlong Item_func_le::val_int()
{
+ DBUG_ASSERT(fixed == 1);
int value= cmp.compare();
return value <= 0 && !null_value ? 1 : 0;
}
@@ -613,6 +630,7 @@ longlong Item_func_le::val_int()
longlong Item_func_lt::val_int()
{
+ DBUG_ASSERT(fixed == 1);
int value= cmp.compare();
return value < 0 && !null_value ? 1 : 0;
}
@@ -620,6 +638,7 @@ longlong Item_func_lt::val_int()
longlong Item_func_strcmp::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *a=args[0]->val_str(&tmp_value1);
String *b=args[1]->val_str(&tmp_value2);
if (!a || !b)
@@ -669,6 +688,7 @@ void Item_func_interval::fix_length_and_dec()
longlong Item_func_interval::val_int()
{
+ DBUG_ASSERT(fixed == 1);
double value= row->el(0)->val();
uint i;
@@ -734,6 +754,7 @@ void Item_func_between::fix_length_and_dec()
longlong Item_func_between::val_int()
{ // ANSI BETWEEN
+ DBUG_ASSERT(fixed == 1);
if (cmp_type == STRING_RESULT)
{
String *value,*a,*b;
@@ -841,6 +862,7 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table)
double
Item_func_ifnull::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if (!args[0]->null_value)
{
@@ -856,6 +878,7 @@ Item_func_ifnull::val()
longlong
Item_func_ifnull::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong value=args[0]->val_int();
if (!args[0]->null_value)
{
@@ -871,6 +894,7 @@ Item_func_ifnull::val_int()
String *
Item_func_ifnull::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
if (!args[0]->null_value)
{
@@ -926,6 +950,7 @@ Item_func_if::fix_length_and_dec()
double
Item_func_if::val()
{
+ DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_int() ? args[1] : args[2];
double value=arg->val();
null_value=arg->null_value;
@@ -935,6 +960,7 @@ Item_func_if::val()
longlong
Item_func_if::val_int()
{
+ DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_int() ? args[1] : args[2];
longlong value=arg->val_int();
null_value=arg->null_value;
@@ -944,6 +970,7 @@ Item_func_if::val_int()
String *
Item_func_if::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_int() ? args[1] : args[2];
String *res=arg->val_str(str);
if (res)
@@ -976,8 +1003,9 @@ Item_func_nullif::fix_length_and_dec()
double
Item_func_nullif::val()
{
+ DBUG_ASSERT(fixed == 1);
double value;
- if (!cmp.compare() || null_value)
+ if (!cmp.compare())
{
null_value=1;
return 0.0;
@@ -990,8 +1018,9 @@ Item_func_nullif::val()
longlong
Item_func_nullif::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong value;
- if (!cmp.compare() || null_value)
+ if (!cmp.compare())
{
null_value=1;
return 0;
@@ -1004,8 +1033,9 @@ Item_func_nullif::val_int()
String *
Item_func_nullif::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res;
- if (!cmp.compare() || null_value)
+ if (!cmp.compare())
{
null_value=1;
return 0;
@@ -1097,6 +1127,7 @@ Item *Item_func_case::find_item(String *str)
String *Item_func_case::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res;
Item *item=find_item(str);
@@ -1114,6 +1145,7 @@ String *Item_func_case::val_str(String *str)
longlong Item_func_case::val_int()
{
+ DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
String dummy_str(buff,sizeof(buff),default_charset());
Item *item=find_item(&dummy_str);
@@ -1131,6 +1163,7 @@ longlong Item_func_case::val_int()
double Item_func_case::val()
{
+ DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
String dummy_str(buff,sizeof(buff),default_charset());
Item *item=find_item(&dummy_str);
@@ -1236,6 +1269,7 @@ void Item_func_case::print(String *str)
String *Item_func_coalesce::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
null_value=0;
for (uint i=0 ; i < arg_count ; i++)
{
@@ -1249,6 +1283,7 @@ String *Item_func_coalesce::val_str(String *str)
longlong Item_func_coalesce::val_int()
{
+ DBUG_ASSERT(fixed == 1);
null_value=0;
for (uint i=0 ; i < arg_count ; i++)
{
@@ -1262,6 +1297,7 @@ longlong Item_func_coalesce::val_int()
double Item_func_coalesce::val()
{
+ DBUG_ASSERT(fixed == 1);
null_value=0;
for (uint i=0 ; i < arg_count ; i++)
{
@@ -1668,6 +1704,7 @@ void Item_func_in::print(String *str)
longlong Item_func_in::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (array)
{
int tmp=array->find(args[0]);
@@ -1691,6 +1728,7 @@ longlong Item_func_in::val_int()
longlong Item_func_bit_or::val_int()
{
+ DBUG_ASSERT(fixed == 1);
ulonglong arg1= (ulonglong) args[0]->val_int();
if (args[0]->null_value)
{
@@ -1710,6 +1748,7 @@ longlong Item_func_bit_or::val_int()
longlong Item_func_bit_and::val_int()
{
+ DBUG_ASSERT(fixed == 1);
ulonglong arg1= (ulonglong) args[0]->val_int();
if (args[0]->null_value)
{
@@ -1748,6 +1787,7 @@ void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
bool
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
List_iterator<Item> li(list);
Item *item;
#ifndef EMBEDDED_LIBRARY
@@ -1775,8 +1815,11 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
if (abort_on_null)
item->top_level_item();
+
+ // item can be substituted in fix_fields
if ((!item->fixed &&
- item->fix_fields(thd, tables, li.ref())) || item->check_cols(1))
+ item->fix_fields(thd, tables, li.ref())) ||
+ (item= *li.ref())->check_cols(1))
return 1; /* purecov: inspected */
used_tables_cache|= item->used_tables();
tmp_table_map= item->not_null_tables();
@@ -1868,14 +1911,27 @@ void Item_cond::print(String *str)
}
-void Item_cond::neg_arguments()
+void Item_cond::neg_arguments(THD *thd)
{
List_iterator<Item> li(list);
Item *item;
while ((item= li++)) /* Apply not transformation to the arguments */
{
- Item *new_item= item->neg_transformer();
- VOID(li.replace(new_item ? new_item : new Item_func_not(item)));
+ Item *new_item= item->neg_transformer(thd);
+ if (!new_item)
+ {
+ new_item= new Item_func_not(item);
+ /*
+ We can use 0 as tables list because Item_func_not do not use it
+ on fix_fields and its arguments are already fixed.
+
+ We do not check results of fix_fields, because there are not way
+ to return error in this functions interface, thd->net.report_error
+ will be checked on upper level call.
+ */
+ new_item->fix_fields(thd, 0, &new_item);
+ }
+ VOID(li.replace(new_item));
}
}
@@ -1900,6 +1956,7 @@ void Item_cond::neg_arguments()
longlong Item_cond_and::val_int()
{
+ DBUG_ASSERT(fixed == 1);
List_iterator_fast<Item> li(list);
Item *item;
null_value= 0;
@@ -1917,6 +1974,7 @@ longlong Item_cond_and::val_int()
longlong Item_cond_or::val_int()
{
+ DBUG_ASSERT(fixed == 1);
List_iterator_fast<Item> li(list);
Item *item;
null_value=0;
@@ -1978,6 +2036,7 @@ Item *and_expressions(Item *a, Item *b, Item **org_item)
longlong Item_func_isnull::val_int()
{
+ DBUG_ASSERT(fixed == 1);
/*
Handle optimization if the argument can't be null
This has to be here because of the test in update_used_tables().
@@ -1989,6 +2048,7 @@ longlong Item_func_isnull::val_int()
longlong Item_is_not_null_test::val_int()
{
+ DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_is_not_null_test::val_int");
if (!used_tables_cache)
{
@@ -2028,6 +2088,7 @@ void Item_is_not_null_test::update_used_tables()
longlong Item_func_isnotnull::val_int()
{
+ DBUG_ASSERT(fixed == 1);
return args[0]->is_null() ? 0 : 1;
}
@@ -2042,6 +2103,7 @@ void Item_func_isnotnull::print(String *str)
longlong Item_func_like::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String* res = args[0]->val_str(&tmp_value1);
if (args[0]->null_value)
{
@@ -2087,6 +2149,7 @@ Item_func::optimize_type Item_func_like::select_optimize() const
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
+ DBUG_ASSERT(fixed == 0);
if (Item_bool_func2::fix_fields(thd, tlist, ref))
return 1;
@@ -2140,6 +2203,7 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
bool
Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
if (args[0]->fix_fields(thd, tables, args) || args[0]->check_cols(1) ||
args[1]->fix_fields(thd,tables, args + 1) || args[1]->check_cols(1))
return 1; /* purecov: inspected */
@@ -2187,6 +2251,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
longlong Item_func_regex::val_int()
{
+ DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
String *res, tmp(buff,sizeof(buff),&my_charset_bin);
@@ -2487,6 +2552,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
longlong Item_cond_xor::val_int()
{
+ DBUG_ASSERT(fixed == 1);
List_iterator<Item> li(list);
Item *item;
int result=0;
@@ -2508,6 +2574,7 @@ longlong Item_cond_xor::val_int()
SYNPOSIS
neg_transformer()
+ thd thread handler
DESCRIPTION
Transform the item using next rules:
@@ -2531,62 +2598,116 @@ longlong Item_cond_xor::val_int()
NULL if we cannot apply NOT transformation (see Item::neg_transformer()).
*/
-Item *Item_func_not::neg_transformer() /* NOT(x) -> x */
+Item *Item_func_not::neg_transformer(THD *thd) /* NOT(x) -> x */
{
- /* We should apply negation elimination to the argument of the NOT function */
- return eliminate_not_funcs(args[0]);
+ // We should apply negation elimination to the argument of the NOT function
+ return eliminate_not_funcs(thd, args[0]);
}
-Item *Item_func_eq::neg_transformer() /* a = b -> a != b */
+
+Item *Item_bool_rowready_func2::neg_transformer(THD *thd)
{
- return new Item_func_ne(args[0], args[1]);
+ Item *item= negated_item();
+ if (item)
+ {
+ /*
+ We can use 0 as tables list because Item_func* family do not use it
+ on fix_fields and its arguments are already fixed.
+
+ We do not check results of fix_fields, because there are not way
+ to return error in this functions interface, thd->net.report_error
+ will be checked on upper level call.
+ */
+ item->fix_fields(thd, 0, &item);
+ }
+ return item;
}
-Item *Item_func_ne::neg_transformer() /* a != b -> a = b */
+
+/* a IS NULL -> a IS NOT NULL */
+Item *Item_func_isnull::neg_transformer(THD *thd)
{
- return new Item_func_eq(args[0], args[1]);
+ Item *item= new Item_func_isnotnull(args[0]);
+ // see comment before fix_fields in Item_bool_rowready_func2::neg_transformer
+ if (item)
+ item->fix_fields(thd, 0, &item);
+ return item;
}
-Item *Item_func_lt::neg_transformer() /* a < b -> a >= b */
+
+/* a IS NOT NULL -> a IS NULL */
+Item *Item_func_isnotnull::neg_transformer(THD *thd)
{
- return new Item_func_ge(args[0], args[1]);
+ Item *item= new Item_func_isnull(args[0]);
+ // see comment before fix_fields in Item_bool_rowready_func2::neg_transformer
+ if (item)
+ item->fix_fields(thd, 0, &item);
+ return item;
+}
+
+
+Item *Item_cond_and::neg_transformer(THD *thd) /* NOT(a AND b AND ...) -> */
+ /* NOT a OR NOT b OR ... */
+{
+ neg_arguments(thd);
+ Item *item= new Item_cond_or(list);
+ // see comment before fix_fields in Item_bool_rowready_func2::neg_transformer
+ if (item)
+ item->fix_fields(thd, 0, &item);
+ return item;
}
-Item *Item_func_ge::neg_transformer() /* a >= b -> a < b */
+
+Item *Item_cond_or::neg_transformer(THD *thd) /* NOT(a OR b OR ...) -> */
+ /* NOT a AND NOT b AND ... */
{
- return new Item_func_lt(args[0], args[1]);
+ neg_arguments(thd);
+ Item *item= new Item_cond_and(list);
+ // see comment before fix_fields in Item_bool_rowready_func2::neg_transformer
+ if (item)
+ item->fix_fields(thd, 0, &item);
+ return item;
}
-Item *Item_func_gt::neg_transformer() /* a > b -> a <= b */
+
+Item *Item_func_eq::negated_item() /* a = b -> a != b */
{
- return new Item_func_le(args[0], args[1]);
+ return new Item_func_ne(args[0], args[1]);
}
-Item *Item_func_le::neg_transformer() /* a <= b -> a > b */
+
+Item *Item_func_ne::negated_item() /* a != b -> a = b */
{
- return new Item_func_gt(args[0], args[1]);
+ return new Item_func_eq(args[0], args[1]);
}
-Item *Item_func_isnull::neg_transformer() /* a IS NULL -> a IS NOT NULL */
+
+Item *Item_func_lt::negated_item() /* a < b -> a >= b */
{
- return new Item_func_isnotnull(args[0]);
+ return new Item_func_ge(args[0], args[1]);
}
-Item *Item_func_isnotnull::neg_transformer() /* a IS NOT NULL -> a IS NULL */
+
+Item *Item_func_ge::negated_item() /* a >= b -> a < b */
{
- return new Item_func_isnull(args[0]);
+ return new Item_func_lt(args[0], args[1]);
}
-Item *Item_cond_and::neg_transformer() /* NOT(a AND b AND ...) -> */
- /* NOT a OR NOT b OR ... */
+
+Item *Item_func_gt::negated_item() /* a > b -> a <= b */
{
- neg_arguments();
- return new Item_cond_or(list);
+ return new Item_func_le(args[0], args[1]);
}
-Item *Item_cond_or::neg_transformer() /* NOT(a OR b OR ...) -> */
- /* NOT a AND NOT b AND ... */
+
+Item *Item_func_le::negated_item() /* a <= b -> a > b */
+{
+ return new Item_func_gt(args[0], args[1]);
+}
+
+// just fake method, should never be called
+Item *Item_bool_rowready_func2::negated_item()
{
- neg_arguments();
- return new Item_cond_and(list);
+ DBUG_ASSERT(0);
+ return 0;
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 9d39ddf4e76..95520c0c222 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -218,6 +218,8 @@ public:
tmp_arg[1]= orig_b;
DBUG_VOID_RETURN;
}
+ Item *neg_transformer(THD *thd);
+ virtual Item *negated_item();
};
class Item_func_not :public Item_bool_func
@@ -227,7 +229,7 @@ public:
longlong val_int();
enum Functype functype() const { return NOT_FUNC; }
const char *func_name() const { return "not"; }
- Item *neg_transformer();
+ Item *neg_transformer(THD *thd);
};
class Item_func_not_all :public Item_func_not
@@ -254,7 +256,7 @@ public:
enum Functype rev_functype() const { return EQ_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "="; }
- Item *neg_transformer();
+ Item *negated_item();
};
class Item_func_equal :public Item_bool_rowready_func2
@@ -267,6 +269,7 @@ public:
enum Functype rev_functype() const { return EQUAL_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "<=>"; }
+ Item* neg_transformer(THD *thd) { return 0; }
};
@@ -279,7 +282,7 @@ public:
enum Functype rev_functype() const { return LE_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return ">="; }
- Item *neg_transformer();
+ Item *negated_item();
};
@@ -292,7 +295,7 @@ public:
enum Functype rev_functype() const { return LT_FUNC; }
cond_result eq_cmp_result() const { return COND_FALSE; }
const char *func_name() const { return ">"; }
- Item *neg_transformer();
+ Item *negated_item();
};
@@ -305,7 +308,7 @@ public:
enum Functype rev_functype() const { return GE_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "<="; }
- Item *neg_transformer();
+ Item *negated_item();
};
@@ -318,7 +321,7 @@ public:
enum Functype rev_functype() const { return GT_FUNC; }
cond_result eq_cmp_result() const { return COND_FALSE; }
const char *func_name() const { return "<"; }
- Item *neg_transformer();
+ Item *negated_item();
};
@@ -331,7 +334,7 @@ public:
cond_result eq_cmp_result() const { return COND_FALSE; }
optimize_type select_optimize() const { return OPTIMIZE_KEY; }
const char *func_name() const { return "<>"; }
- Item *neg_transformer();
+ Item *negated_item();
};
@@ -409,6 +412,7 @@ public:
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
args[0]->top_level_item();
return Item_func::fix_fields(thd, tlist, ref);
}
@@ -726,6 +730,7 @@ class Item_func_in :public Item_int_func
void cleanup()
{
DBUG_ENTER("Item_func_in::cleanup");
+ Item_int_func::cleanup();
delete array;
delete in_item;
array= 0;
@@ -778,7 +783,7 @@ public:
}
table_map not_null_tables() const { return 0; }
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
- Item *neg_transformer();
+ Item *neg_transformer(THD *thd);
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
};
@@ -812,7 +817,7 @@ public:
const char *func_name() const { return "isnotnull"; }
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
table_map not_null_tables() const { return 0; }
- Item *neg_transformer();
+ Item *neg_transformer(THD *thd);
void print(String *str);
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
};
@@ -920,7 +925,7 @@ public:
void top_level_item() { abort_on_null=1; }
void copy_andor_arguments(THD *thd, Item_cond *item);
bool walk(Item_processor processor, byte *arg);
- void neg_arguments();
+ void neg_arguments(THD *thd);
};
@@ -941,7 +946,7 @@ public:
item->copy_andor_arguments(thd, this);
return item;
}
- Item *neg_transformer();
+ Item *neg_transformer(THD *thd);
};
class Item_cond_or :public Item_cond
@@ -962,7 +967,7 @@ public:
item->copy_andor_arguments(thd, this);
return item;
}
- Item *neg_transformer();
+ Item *neg_transformer(THD *thd);
};
@@ -986,13 +991,13 @@ public:
/* Some usefull inline functions */
-inline Item *and_conds(Item *a,Item *b)
+inline Item *and_conds(Item *a, Item *b, TABLE_LIST *tables)
{
if (!b) return a;
if (!a) return b;
- Item *cond=new Item_cond_and(a,b);
+ Item *cond= new Item_cond_and(a,b);
if (cond)
- cond->update_used_tables();
+ cond->fix_fields(current_thd, tables, &cond);
return cond;
}
diff --git a/sql/item_create.cc b/sql/item_create.cc
index eda3d43afdc..74f36de11ac 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -426,6 +426,11 @@ Item *create_func_ucase(Item* a)
return new Item_func_ucase(a);
}
+Item *create_func_unhex(Item* a)
+{
+ return new Item_func_unhex(a);
+}
+
Item *create_func_uuid(void)
{
return new Item_func_uuid();
@@ -460,6 +465,7 @@ Item *create_func_cast(Item *a, Cast_target cast_type, int len,
{
Item *res;
LINT_INIT(res);
+
switch (cast_type) {
case ITEM_CAST_BINARY: res= new Item_func_binary(a); break;
case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break;
diff --git a/sql/item_create.h b/sql/item_create.h
index a6a3c9e1841..7577627ef04 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -92,6 +92,7 @@ Item *create_func_time_format(Item *a, Item *b);
Item *create_func_time_to_sec(Item* a);
Item *create_func_to_days(Item* a);
Item *create_func_ucase(Item* a);
+Item *create_func_unhex(Item* a);
Item *create_func_uuid(void);
Item *create_func_version(void);
Item *create_func_weekday(Item* a);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 0327204dbfd..5151fb2876d 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -29,6 +29,16 @@
#include <ft_global.h>
+bool check_reserved_words(LEX_STRING *name)
+{
+ if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
+ !my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
+ !my_strcasecmp(system_charset_info, name->str, "SESSION"))
+ return TRUE;
+ return FALSE;
+}
+
+
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
const char *fname)
{
@@ -189,6 +199,7 @@ Item_func::Item_func(THD *thd, Item_func *item)
bool
Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
Item **arg,**arg_end;
#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
char buff[STACK_BUFF_ALLOC]; // Max argument in function
@@ -204,8 +215,11 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
Item *item;
- /* We can't yet set item to *arg as fix_fields may change *arg */
- if ((*arg)->fix_fields(thd, tables, arg) ||
+ /*
+ We can't yet set item to *arg as fix_fields may change *arg
+ We shouldn't call fix_fields() twice, so check 'fixed' field first
+ */
+ if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)) ||
(*arg)->check_cols(allowed_arg_cols))
return 1; /* purecov: inspected */
item= *arg;
@@ -370,6 +384,7 @@ Field *Item_func::tmp_table_field(TABLE *t_arg)
String *Item_real_func::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
double nr=val();
if (null_value)
return 0; /* purecov: inspected */
@@ -380,6 +395,7 @@ String *Item_real_func::val_str(String *str)
String *Item_num_func::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if (hybrid_type == INT_RESULT)
{
longlong nr=val_int();
@@ -418,6 +434,7 @@ Item *Item_func::get_tmp_table_item(THD *thd)
String *Item_int_func::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
longlong nr=val_int();
if (null_value)
return 0;
@@ -445,6 +462,7 @@ void Item_num_op::find_num_type(void)
String *Item_num_op::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if (hybrid_type == INT_RESULT)
{
longlong nr=val_int();
@@ -486,6 +504,7 @@ void Item_func_unsigned::print(String *str)
double Item_func_plus::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val()+args[1]->val();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
@@ -494,6 +513,7 @@ double Item_func_plus::val()
longlong Item_func_plus::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (hybrid_type == INT_RESULT)
{
longlong value=args[0]->val_int()+args[1]->val_int();
@@ -521,6 +541,7 @@ void Item_func_minus::fix_length_and_dec()
double Item_func_minus::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val() - args[1]->val();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
@@ -529,6 +550,7 @@ double Item_func_minus::val()
longlong Item_func_minus::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (hybrid_type == INT_RESULT)
{
longlong value=args[0]->val_int() - args[1]->val_int();
@@ -542,6 +564,7 @@ longlong Item_func_minus::val_int()
double Item_func_mul::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val()*args[1]->val();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0; /* purecov: inspected */
@@ -550,6 +573,7 @@ double Item_func_mul::val()
longlong Item_func_mul::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (hybrid_type == INT_RESULT)
{
longlong value=args[0]->val_int()*args[1]->val_int();
@@ -563,6 +587,7 @@ longlong Item_func_mul::val_int()
double Item_func_div::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
double val2=args[1]->val();
if ((null_value= val2 == 0.0 || args[0]->null_value || args[1]->null_value))
@@ -572,6 +597,7 @@ double Item_func_div::val()
longlong Item_func_div::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (hybrid_type == INT_RESULT)
{
longlong value=args[0]->val_int();
@@ -596,6 +622,7 @@ void Item_func_div::fix_length_and_dec()
/* Integer division */
longlong Item_func_int_div::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong value=args[0]->val_int();
longlong val2=args[1]->val_int();
if ((null_value= val2 == 0 || args[0]->null_value || args[1]->null_value))
@@ -616,6 +643,7 @@ void Item_func_int_div::fix_length_and_dec()
double Item_func_mod::val()
{
+ DBUG_ASSERT(fixed == 1);
double value= floor(args[0]->val()+0.5);
double val2=floor(args[1]->val()+0.5);
if ((null_value=val2 == 0.0 || args[0]->null_value || args[1]->null_value))
@@ -625,6 +653,7 @@ double Item_func_mod::val()
longlong Item_func_mod::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong value= args[0]->val_int();
longlong val2= args[1]->val_int();
if ((null_value=val2 == 0 || args[0]->null_value || args[1]->null_value))
@@ -643,6 +672,7 @@ void Item_func_mod::fix_length_and_dec()
double Item_func_neg::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
null_value=args[0]->null_value;
return -value;
@@ -651,6 +681,7 @@ double Item_func_neg::val()
longlong Item_func_neg::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong value=args[0]->val_int();
null_value=args[0]->null_value;
return -value;
@@ -684,6 +715,7 @@ void Item_func_neg::fix_length_and_dec()
double Item_func_abs::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
null_value=args[0]->null_value;
return fabs(value);
@@ -692,6 +724,7 @@ double Item_func_abs::val()
longlong Item_func_abs::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong value=args[0]->val_int();
null_value=args[0]->null_value;
return value >= 0 ? value : -value;
@@ -714,6 +747,7 @@ void Item_func_abs::fix_length_and_dec()
/* Gateway to natural LOG function */
double Item_func_ln::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0;
@@ -727,6 +761,7 @@ double Item_func_ln::val()
*/
double Item_func_log::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0;
@@ -742,6 +777,7 @@ double Item_func_log::val()
double Item_func_log2::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0;
@@ -750,6 +786,7 @@ double Item_func_log2::val()
double Item_func_log10::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0; /* purecov: inspected */
@@ -758,6 +795,7 @@ double Item_func_log10::val()
double Item_func_exp::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=args[0]->null_value))
return 0.0; /* purecov: inspected */
@@ -766,6 +804,7 @@ double Item_func_exp::val()
double Item_func_sqrt::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=(args[0]->null_value || value < 0)))
return 0.0; /* purecov: inspected */
@@ -774,6 +813,7 @@ double Item_func_sqrt::val()
double Item_func_pow::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
double val2=args[1]->val();
if ((null_value=(args[0]->null_value || args[1]->null_value)))
@@ -785,6 +825,7 @@ double Item_func_pow::val()
double Item_func_acos::val()
{
+ DBUG_ASSERT(fixed == 1);
// the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
volatile double value=args[0]->val();
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
@@ -794,6 +835,7 @@ double Item_func_acos::val()
double Item_func_asin::val()
{
+ DBUG_ASSERT(fixed == 1);
// the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
volatile double value=args[0]->val();
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
@@ -803,6 +845,7 @@ double Item_func_asin::val()
double Item_func_atan::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=args[0]->null_value))
return 0.0;
@@ -818,6 +861,7 @@ double Item_func_atan::val()
double Item_func_cos::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=args[0]->null_value))
return 0.0;
@@ -826,6 +870,7 @@ double Item_func_cos::val()
double Item_func_sin::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=args[0]->null_value))
return 0.0;
@@ -834,6 +879,7 @@ double Item_func_sin::val()
double Item_func_tan::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=args[0]->null_value))
return 0.0;
@@ -846,6 +892,7 @@ double Item_func_tan::val()
longlong Item_func_shift_left::val_int()
{
+ DBUG_ASSERT(fixed == 1);
uint shift;
ulonglong res= ((ulonglong) args[0]->val_int() <<
(shift=(uint) args[1]->val_int()));
@@ -860,6 +907,7 @@ longlong Item_func_shift_left::val_int()
longlong Item_func_shift_right::val_int()
{
+ DBUG_ASSERT(fixed == 1);
uint shift;
ulonglong res= (ulonglong) args[0]->val_int() >>
(shift=(uint) args[1]->val_int());
@@ -875,6 +923,7 @@ longlong Item_func_shift_right::val_int()
longlong Item_func_bit_neg::val_int()
{
+ DBUG_ASSERT(fixed == 1);
ulonglong res= (ulonglong) args[0]->val_int();
if ((null_value=args[0]->null_value))
return 0;
@@ -894,6 +943,7 @@ void Item_func_integer::fix_length_and_dec()
longlong Item_func_ceiling::val_int()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
null_value=args[0]->null_value;
return (longlong) ceil(value);
@@ -901,7 +951,9 @@ longlong Item_func_ceiling::val_int()
longlong Item_func_floor::val_int()
{
- double value=args[0]->val();
+ DBUG_ASSERT(fixed == 1);
+ // the volatile's for BUG #3051 to calm optimizer down (because of gcc's bug)
+ volatile double value=args[0]->val();
null_value=args[0]->null_value;
return (longlong) floor(value);
}
@@ -922,6 +974,7 @@ void Item_func_round::fix_length_and_dec()
double Item_func_round::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
int dec=(int) args[1]->val_int();
uint abs_dec=abs(dec);
@@ -954,6 +1007,7 @@ void Item_func_rand::fix_length_and_dec()
{
decimals=NOT_FIXED_DEC;
max_length=float_length(decimals);
+ used_tables_cache|= RAND_TABLE_BIT;
if (arg_count)
{ // Only use argument once in query
uint32 tmp= (uint32) (args[0]->val_int());
@@ -979,14 +1033,22 @@ void Item_func_rand::fix_length_and_dec()
}
}
+void Item_func_rand::update_used_tables()
+{
+ Item_real_func::update_used_tables();
+ used_tables_cache|= RAND_TABLE_BIT;
+}
+
double Item_func_rand::val()
{
+ DBUG_ASSERT(fixed == 1);
return my_rnd(rand);
}
longlong Item_func_sign::val_int()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
null_value=args[0]->null_value;
return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
@@ -995,6 +1057,7 @@ longlong Item_func_sign::val_int()
double Item_func_units::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=args[0]->val();
if ((null_value=args[0]->null_value))
return 0;
@@ -1026,6 +1089,7 @@ void Item_func_min_max::fix_length_and_dec()
String *Item_func_min_max::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
switch (cmp_type) {
case INT_RESULT:
{
@@ -1087,6 +1151,7 @@ String *Item_func_min_max::val_str(String *str)
double Item_func_min_max::val()
{
+ DBUG_ASSERT(fixed == 1);
double value=0.0;
null_value=1;
for (uint i=0; i < arg_count ; i++)
@@ -1109,6 +1174,7 @@ double Item_func_min_max::val()
longlong Item_func_min_max::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong value=0;
null_value=1;
for (uint i=0; i < arg_count ; i++)
@@ -1130,6 +1196,7 @@ longlong Item_func_min_max::val_int()
longlong Item_func_length::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
if (!res)
{
@@ -1143,6 +1210,7 @@ longlong Item_func_length::val_int()
longlong Item_func_char_length::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
if (!res)
{
@@ -1156,6 +1224,7 @@ longlong Item_func_char_length::val_int()
longlong Item_func_coercibility::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (args[0]->null_value)
{
null_value= 1;
@@ -1175,6 +1244,7 @@ void Item_func_locate::fix_length_and_dec()
longlong Item_func_locate::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *a=args[0]->val_str(&value1);
String *b=args[1]->val_str(&value2);
if (!a || !b)
@@ -1225,6 +1295,7 @@ void Item_func_locate::print(String *str)
longlong Item_func_field::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (cmp_type == STRING_RESULT)
{
String *field;
@@ -1272,6 +1343,7 @@ void Item_func_field::fix_length_and_dec()
longlong Item_func_ascii::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
if (!res)
{
@@ -1284,6 +1356,7 @@ longlong Item_func_ascii::val_int()
longlong Item_func_ord::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
if (!res)
{
@@ -1338,6 +1411,7 @@ static const char separator=',';
longlong Item_func_find_in_set::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (enum_value)
{
ulonglong tmp=(ulonglong) args[1]->val_int();
@@ -1391,6 +1465,7 @@ longlong Item_func_find_in_set::val_int()
longlong Item_func_bit_count::val_int()
{
+ DBUG_ASSERT(fixed == 1);
ulonglong value= (ulonglong) args[0]->val_int();
if (args[0]->null_value)
{
@@ -1469,9 +1544,12 @@ 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))
+ DBUG_RETURN(1);
+ // we can't assign 'item' before, because fix_fields() can change arg
Item *item= *arg;
- if (item->fix_fields(thd, tables, arg) || item->check_cols(1))
- return 1;
+ if (item->check_cols(1))
+ DBUG_RETURN(1);
/*
TODO: We should think about this. It is not always
right way just to set an UDF result to return my_charset_bin
@@ -1660,6 +1738,7 @@ String *udf_handler::val_str(String *str,String *save_str)
double Item_func_udf_float::val()
{
+ DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_func_udf_float::val");
DBUG_PRINT("info",("result_type: %d arg_count: %d",
args[0]->result_type(), arg_count));
@@ -1669,6 +1748,7 @@ double Item_func_udf_float::val()
String *Item_func_udf_float::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
double nr=val();
if (null_value)
return 0; /* purecov: inspected */
@@ -1679,6 +1759,7 @@ String *Item_func_udf_float::val_str(String *str)
longlong Item_func_udf_int::val_int()
{
+ DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_func_udf_int::val_int");
DBUG_PRINT("info",("result_type: %d arg_count: %d",
args[0]->result_type(), arg_count));
@@ -1689,6 +1770,7 @@ longlong Item_func_udf_int::val_int()
String *Item_func_udf_int::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
longlong nr=val_int();
if (null_value)
return 0;
@@ -1712,6 +1794,7 @@ void Item_func_udf_str::fix_length_and_dec()
String *Item_func_udf_str::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res=udf.val_str(str,&str_value);
null_value = !res;
return res;
@@ -1728,7 +1811,7 @@ bool udf_handler::get_arguments() { return 0; }
pthread_mutex_t LOCK_user_locks;
static HASH hash_user_locks;
-class ULL
+class User_level_lock
{
char *key;
uint key_length;
@@ -1740,7 +1823,7 @@ public:
pthread_t thread;
ulong thread_id;
- ULL(const char *key_arg,uint length, ulong id)
+ User_level_lock(const char *key_arg,uint length, ulong id)
:key_length(length),count(1),locked(1), thread_id(id)
{
key=(char*) my_memdup((byte*) key_arg,length,MYF(0));
@@ -1754,7 +1837,7 @@ public:
}
}
}
- ~ULL()
+ ~User_level_lock()
{
if (key)
{
@@ -1764,11 +1847,12 @@ public:
pthread_cond_destroy(&cond);
}
inline bool initialized() { return key != 0; }
- friend void item_user_lock_release(ULL *ull);
- friend char *ull_get_key(const ULL *ull,uint *length,my_bool not_used);
+ friend void item_user_lock_release(User_level_lock *ull);
+ friend char *ull_get_key(const User_level_lock *ull, uint *length,
+ my_bool not_used);
};
-char *ull_get_key(const ULL *ull,uint *length,
+char *ull_get_key(const User_level_lock *ull, uint *length,
my_bool not_used __attribute__((unused)))
{
*length=(uint) ull->key_length;
@@ -1796,7 +1880,7 @@ void item_user_lock_free(void)
}
}
-void item_user_lock_release(ULL *ull)
+void item_user_lock_release(User_level_lock *ull)
{
ull->locked=0;
if (mysql_bin_log.is_open())
@@ -1824,6 +1908,7 @@ void item_user_lock_release(ULL *ull)
longlong Item_master_pos_wait::val_int()
{
+ DBUG_ASSERT(fixed == 1);
THD* thd = current_thd;
String *log_name = args[0]->val_str(&value);
int event_count= 0;
@@ -1837,13 +1922,11 @@ longlong Item_master_pos_wait::val_int()
longlong pos = (ulong)args[1]->val_int();
longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
#ifdef HAVE_REPLICATION
- LOCK_ACTIVE_MI;
- if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
- {
+ if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
+ {
null_value = 1;
event_count=0;
}
- UNLOCK_ACTIVE_MI;
#endif
return event_count;
}
@@ -1852,7 +1935,7 @@ longlong Item_master_pos_wait::val_int()
void debug_sync_point(const char* lock_name, uint lock_timeout)
{
THD* thd=current_thd;
- ULL* ull;
+ User_level_lock* ull;
struct timespec abstime;
int lock_name_len,error=0;
lock_name_len=strlen(lock_name);
@@ -1870,7 +1953,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
this case, we will not be waiting, but rather, just waste CPU and
memory on the whole deal
*/
- if (!(ull= ((ULL*) hash_search(&hash_user_locks,lock_name,
+ if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks, lock_name,
lock_name_len))))
{
pthread_mutex_unlock(&LOCK_user_locks);
@@ -1927,11 +2010,12 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
longlong Item_func_get_lock::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
longlong timeout=args[1]->val_int();
struct timespec abstime;
THD *thd=current_thd;
- ULL *ull;
+ User_level_lock *ull;
int error=0;
pthread_mutex_lock(&LOCK_user_locks);
@@ -1950,10 +2034,11 @@ longlong Item_func_get_lock::val_int()
thd->ull=0;
}
- if (!(ull= ((ULL*) hash_search(&hash_user_locks,(byte*) res->ptr(),
- res->length()))))
+ if (!(ull= ((User_level_lock *) hash_search(&hash_user_locks,
+ (byte*) res->ptr(),
+ res->length()))))
{
- ull=new ULL(res->ptr(),res->length(), thd->thread_id);
+ ull=new User_level_lock(res->ptr(),res->length(), thd->thread_id);
if (!ull || !ull->initialized())
{
delete ull;
@@ -2021,8 +2106,9 @@ longlong Item_func_get_lock::val_int()
longlong Item_func_release_lock::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
- ULL *ull;
+ User_level_lock *ull;
longlong result;
if (!res || !res->length())
{
@@ -2033,8 +2119,9 @@ longlong Item_func_release_lock::val_int()
result=0;
pthread_mutex_lock(&LOCK_user_locks);
- if (!(ull= ((ULL*) hash_search(&hash_user_locks,(const byte*) res->ptr(),
- res->length()))))
+ if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks,
+ (const byte*) res->ptr(),
+ res->length()))))
{
null_value=1;
}
@@ -2054,6 +2141,7 @@ longlong Item_func_release_lock::val_int()
longlong Item_func_set_last_insert_id::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong value=args[0]->val_int();
current_thd->insert_id(value);
null_value=args[0]->null_value;
@@ -2064,6 +2152,7 @@ longlong Item_func_set_last_insert_id::val_int()
longlong Item_func_benchmark::val_int()
{
+ DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff), &my_charset_bin);
THD *thd=current_thd;
@@ -2156,6 +2245,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
if (Item_func::fix_fields(thd, tables, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
@@ -2420,6 +2510,7 @@ Item_func_set_user_var::update()
double Item_func_set_user_var::val()
{
+ DBUG_ASSERT(fixed == 1);
check();
update(); // Store expression
return entry->val(&null_value);
@@ -2427,6 +2518,7 @@ double Item_func_set_user_var::val()
longlong Item_func_set_user_var::val_int()
{
+ DBUG_ASSERT(fixed == 1);
check();
update(); // Store expression
return entry->val_int(&null_value);
@@ -2434,6 +2526,7 @@ longlong Item_func_set_user_var::val_int()
String *Item_func_set_user_var::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
check();
update(); // Store expression
return entry->val_str(&null_value, str, decimals);
@@ -2453,6 +2546,7 @@ void Item_func_set_user_var::print(String *str)
String *
Item_func_get_user_var::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_func_get_user_var::val_str");
if (!var_entry)
DBUG_RETURN((String*) 0); // No such variable
@@ -2462,6 +2556,7 @@ Item_func_get_user_var::val_str(String *str)
double Item_func_get_user_var::val()
{
+ DBUG_ASSERT(fixed == 1);
if (!var_entry)
return 0.0; // No such variable
return (var_entry->val(&null_value));
@@ -2470,6 +2565,7 @@ double Item_func_get_user_var::val()
longlong Item_func_get_user_var::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (!var_entry)
return LL(0); // No such variable
return (var_entry->val_int(&null_value));
@@ -2616,6 +2712,7 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
longlong Item_func_inet_aton::val_int()
{
+ DBUG_ASSERT(fixed == 1);
uint byte_result = 0;
ulonglong result = 0; // We are ready for 64 bit addresses
const char *p,* end;
@@ -2683,6 +2780,13 @@ void Item_func_match::init_search(bool no_order)
fields.push_back(args[i]);
concat=new Item_func_concat_ws(new Item_string(" ",1,
cmp_collation.collation), fields);
+ /*
+ Above function used only to get value and do not need fix_fields for it:
+ Item_string - basic constant
+ fields - fix_fieds already was called for this arguments
+ Item_func_concat_ws - do not need fix_fields to produce value
+ */
+ concat->quick_fix_field();
}
if (master)
@@ -2725,6 +2829,7 @@ void Item_func_match::init_search(bool no_order)
bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
Item *item;
LINT_INIT(item); // Safe as arg_count is > 1
@@ -2869,6 +2974,7 @@ bool Item_func_match::eq(const Item *item, bool binary_cmp) const
double Item_func_match::val()
{
+ DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_func_match::val");
if (ft_handler == NULL)
DBUG_RETURN(-1.0);
@@ -2911,6 +3017,7 @@ void Item_func_match::print(String *str)
longlong Item_func_bit_xor::val_int()
{
+ DBUG_ASSERT(fixed == 1);
ulonglong arg1= (ulonglong) args[0]->val_int();
ulonglong arg2= (ulonglong) args[1]->val_int();
if ((null_value= (args[0]->null_value || args[1]->null_value)))
@@ -3039,9 +3146,10 @@ Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
longlong Item_func_is_free_lock::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
THD *thd=current_thd;
- ULL *ull;
+ User_level_lock *ull;
null_value=0;
if (!res || !res->length())
@@ -3051,7 +3159,7 @@ longlong Item_func_is_free_lock::val_int()
}
pthread_mutex_lock(&LOCK_user_locks);
- ull= (ULL*) hash_search(&hash_user_locks,(byte*) res->ptr(),
+ ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(),
res->length());
pthread_mutex_unlock(&LOCK_user_locks);
if (!ull || !ull->locked)
@@ -3061,16 +3169,17 @@ longlong Item_func_is_free_lock::val_int()
longlong Item_func_is_used_lock::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
THD *thd=current_thd;
- ULL *ull;
+ User_level_lock *ull;
null_value=1;
if (!res || !res->length())
return 0;
pthread_mutex_lock(&LOCK_user_locks);
- ull= (ULL*) hash_search(&hash_user_locks,(byte*) res->ptr(),
+ ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(),
res->length());
pthread_mutex_unlock(&LOCK_user_locks);
if (!ull || !ull->locked)
diff --git a/sql/item_func.h b/sql/item_func.h
index 3890e7c6de5..4558c1c6f62 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -155,7 +155,7 @@ public:
Item_real_func(Item *a,Item *b) :Item_func(a,b) {}
Item_real_func(List<Item> &list) :Item_func(list) {}
String *val_str(String*str);
- longlong val_int() { return (longlong) val(); }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return (longlong) val(); }
enum Item_result result_type () const { return REAL_RESULT; }
void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
};
@@ -169,7 +169,7 @@ public:
Item_num_func(Item *a) :Item_func(a),hybrid_type(REAL_RESULT) {}
Item_num_func(Item *a,Item *b) :Item_func(a,b),hybrid_type(REAL_RESULT) {}
String *val_str(String*str);
- longlong val_int() { return (longlong) val(); }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return (longlong) val(); }
enum Item_result result_type () const { return hybrid_type; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
bool is_null() { (void) val(); return null_value; }
@@ -200,7 +200,7 @@ public:
Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; }
Item_int_func(List<Item> &list) :Item_func(list) { max_length=21; }
Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) {}
- double val() { return (double) val_int(); }
+ double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() {}
@@ -285,7 +285,7 @@ class Item_func_int_div :public Item_num_op
public:
Item_func_int_div(Item *a,Item *b) :Item_num_op(a,b)
{ hybrid_type=INT_RESULT; }
- double val() { return (double) val_int(); }
+ double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
longlong val_int();
const char *func_name() const { return "DIV"; }
void fix_length_and_dec();
@@ -512,7 +512,7 @@ public:
double val();
const char *func_name() const { return "rand"; }
bool const_item() const { return 0; }
- table_map used_tables() const { return RAND_TABLE_BIT; }
+ void update_used_tables();
void fix_length_and_dec();
};
@@ -584,7 +584,8 @@ class Item_func_bit_length :public Item_func_length
{
public:
Item_func_bit_length(Item *a) :Item_func_length(a) {}
- longlong val_int() { return Item_func_length::val_int()*8; }
+ longlong val_int()
+ { DBUG_ASSERT(fixed == 1); return Item_func_length::val_int()*8; }
const char *func_name() const { return "bit_length"; }
};
@@ -765,6 +766,7 @@ public:
const char *func_name() const { return udf.name(); }
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
bool res= udf.fix_fields(thd, tables, this, arg_count, args);
used_tables_cache= udf.used_tables_cache;
const_item_cache= udf.const_item_cache;
@@ -782,7 +784,8 @@ class Item_func_udf_float :public Item_udf_func
Item_func_udf_float(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
:Item_udf_func(udf_arg,list) {}
- longlong val_int() { return (longlong) Item_func_udf_float::val(); }
+ longlong val_int()
+ { DBUG_ASSERT(fixed == 1); return (longlong) Item_func_udf_float::val(); }
double val();
String *val_str(String *str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
@@ -833,7 +836,7 @@ class Item_func_udf_float :public Item_real_func
public:
Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {}
Item_func_udf_float(udf_func *udf_arg, List<Item> &list) :Item_real_func(list) {}
- double val() { return 0.0; }
+ double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
};
@@ -842,7 +845,7 @@ class Item_func_udf_int :public Item_int_func
public:
Item_func_udf_int(udf_func *udf_arg) :Item_int_func() {}
Item_func_udf_int(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {}
- longlong val_int() { return 0; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
};
@@ -851,9 +854,10 @@ class Item_func_udf_str :public Item_func
public:
Item_func_udf_str(udf_func *udf_arg) :Item_func() {}
Item_func_udf_str(udf_func *udf_arg, List<Item> &list) :Item_func(list) {}
- String *val_str(String *) { null_value=1; return 0; }
- double val() { null_value=1; return 0.0; }
- longlong val_int() { null_value=1; return 0; }
+ String *val_str(String *)
+ { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
+ double val() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec() { maybe_null=1; max_length=0; }
};
@@ -864,9 +868,9 @@ public:
** User level locks
*/
-class ULL;
+class User_level_lock;
void item_user_lock_init(void);
-void item_user_lock_release(ULL *ull);
+void item_user_lock_release(User_level_lock *ull);
void item_user_lock_free(void);
class Item_func_get_lock :public Item_int_func
@@ -1000,6 +1004,7 @@ public:
void cleanup()
{
DBUG_ENTER("Item_func_match");
+ Item_real_func::cleanup();
if (!master && ft_handler)
{
ft_handler->please->close_search(ft_handler);
@@ -1021,7 +1026,7 @@ public:
table_map not_null_tables() const { return 0; }
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
- longlong val_int() { return val()!=0.0; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return val()!=0.0; }
double val();
void print(String *str);
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 6934ad9d3b0..a1305e0b1d9 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -27,24 +27,28 @@
#include "sql_acl.h"
#include <m_ctype.h>
+
String *Item_func_geometry_from_text::val_str(String *str)
{
- Geometry geom;
+ DBUG_ASSERT(fixed == 1);
+ Geometry_buffer buffer;
String arg_val;
String *wkt= args[0]->val_str(&arg_val);
- GTextReadStream trs(wkt->ptr(), wkt->length());
- uint32 srid;
+
+ if ((null_value= args[0]->null_value))
+ return 0;
+
+ Gis_read_stream trs(wkt->charset(), wkt->ptr(), wkt->length());
+ uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int();
- else
- srid= 0;
if (str->reserve(SRID_SIZE, 512))
return 0;
str->length(0);
str->q_append(srid);
- if ((null_value=(args[0]->null_value || geom.create_from_wkt(&trs, str, 0))))
+ if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
return 0;
return str;
}
@@ -58,25 +62,25 @@ void Item_func_geometry_from_text::fix_length_and_dec()
String *Item_func_geometry_from_wkb::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String arg_val;
String *wkb= args[0]->val_str(&arg_val);
- Geometry geom;
- uint32 srid;
+ Geometry_buffer buffer;
+ Geometry *geom;
+ uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int();
- else
- srid= 0;
if (str->reserve(SRID_SIZE, 512))
return 0;
str->length(0);
str->q_append(srid);
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(wkb->ptr(), wkb->length()))))
+ if ((null_value=
+ (args[0]->null_value ||
+ !(geom= Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length())) ||
+ str->append(*wkb))))
return 0;
-
- str->append(*wkb);
return str;
}
@@ -89,37 +93,45 @@ void Item_func_geometry_from_wkb::fix_length_and_dec()
String *Item_func_as_wkt::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
-
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
+ Geometry_buffer buffer;
+ Geometry *geom= NULL;
+ const char *dummy;
+
+ if ((null_value=
+ (args[0]->null_value ||
+ !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)))))
return 0;
str->length(0);
-
- if ((null_value= geom.as_wkt(str)))
+ if ((null_value= geom->as_wkt(str, &dummy)))
return 0;
return str;
}
+
void Item_func_as_wkt::fix_length_and_dec()
{
max_length=MAX_BLOB_WIDTH;
}
+
String *Item_func_as_wkb::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
+ if ((null_value=
+ (args[0]->null_value ||
+ !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)))))
return 0;
str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE,
@@ -127,66 +139,78 @@ String *Item_func_as_wkb::val_str(String *str)
return str;
}
+
void Item_func_as_wkb::fix_length_and_dec()
{
max_length= MAX_BLOB_WIDTH;
}
+
String *Item_func_geometry_type::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *swkb= args[0]->val_str(str);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom= NULL;
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
+ if ((null_value=
+ (args[0]->null_value ||
+ !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)))))
return 0;
- str->copy(geom.get_class_info()->m_name,
- strlen(geom.get_class_info()->m_name),
- default_charset());
+ /* String will not move */
+ str->set(geom->get_class_info()->m_name.str,
+ geom->get_class_info()->m_name.length,
+ default_charset());
return str;
}
String *Item_func_envelope::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom= NULL;
+ uint32 srid;
- if ((null_value= args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE)))
+ if ((null_value=
+ args[0]->null_value ||
+ !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE))))
return 0;
- uint32 srid= uint4korr(swkb->ptr());
+ srid= uint4korr(swkb->ptr());
str->length(0);
if (str->reserve(SRID_SIZE, 512))
return 0;
str->q_append(srid);
- return (null_value= geom.envelope(str)) ? 0 : str;
+ return (null_value= geom->envelope(str)) ? 0 : str;
}
String *Item_func_centroid::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom= NULL;
+ uint32 srid;
if ((null_value= args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, centroid)))
+ !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE))))
return 0;
if (str->reserve(SRID_SIZE, 512))
return 0;
str->length(0);
- uint32 srid= uint4korr(swkb->ptr());
+ srid= uint4korr(swkb->ptr());
str->q_append(srid);
- return (null_value= geom.centroid(str)) ? 0 : str;
+ return (null_value= test(geom->centroid(str))) ? 0 : str;
}
@@ -196,91 +220,97 @@ String *Item_func_centroid::val_str(String *str)
String *Item_func_spatial_decomp::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom= NULL;
+ uint32 srid;
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
+ if ((null_value=
+ (args[0]->null_value ||
+ !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)))))
return 0;
- null_value= 1;
+ srid= uint4korr(swkb->ptr());
if (str->reserve(SRID_SIZE, 512))
- return 0;
+ goto err;
str->length(0);
- uint32 srid= uint4korr(swkb->ptr());
str->q_append(srid);
- switch(decomp_func)
- {
+ switch (decomp_func) {
case SP_STARTPOINT:
- if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str))
- goto ret;
+ if (geom->start_point(str))
+ goto err;
break;
case SP_ENDPOINT:
- if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str))
- goto ret;
+ if (geom->end_point(str))
+ goto err;
break;
case SP_EXTERIORRING:
- if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str))
- goto ret;
+ if (geom->exterior_ring(str))
+ goto err;
break;
default:
- goto ret;
+ goto err;
}
- null_value= 0;
+ return str;
-ret:
- return null_value ? 0 : str;
+err:
+ null_value= 1;
+ return 0;
}
String *Item_func_spatial_decomp_n::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
long n= (long) args[1]->val_int();
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom= NULL;
+ uint32 srid;
- if ((null_value= (args[0]->null_value || args[1]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
+ if ((null_value=
+ (args[0]->null_value || args[1]->null_value ||
+ !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)))))
return 0;
- null_value= 1;
if (str->reserve(SRID_SIZE, 512))
- return 0;
+ goto err;
+ srid= uint4korr(swkb->ptr());
str->length(0);
- uint32 srid= uint4korr(swkb->ptr());
str->q_append(srid);
- switch(decomp_func_n)
+ switch (decomp_func_n)
{
case SP_POINTN:
- if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str))
- goto ret;
+ if (geom->point_n(n,str))
+ goto err;
break;
case SP_GEOMETRYN:
- if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str))
- goto ret;
+ if (geom->geometry_n(n,str))
+ goto err;
break;
case SP_INTERIORRINGN:
- if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) ||
- geom.interior_ring_n(n,str))
- goto ret;
+ if (geom->interior_ring_n(n,str))
+ goto err;
break;
default:
- goto ret;
+ goto err;
}
- null_value= 0;
+ return str;
-ret:
- return null_value ? 0 : str;
+err:
+ null_value=1;
+ return 0;
}
@@ -296,17 +326,18 @@ ret:
String *Item_func_point::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
double x= args[0]->val();
double y= args[1]->val();
- if ( (null_value= (args[0]->null_value ||
- args[1]->null_value ||
- str->realloc(1 + 4 + 8 + 8))))
+ if ((null_value= (args[0]->null_value ||
+ args[1]->null_value ||
+ str->realloc(1 + 4 + SIZEOF_STORED_DOUBLE*2))))
return 0;
str->length(0);
- str->q_append((char)Geometry::wkbNDR);
- str->q_append((uint32)Geometry::wkbPoint);
+ str->q_append((char)Geometry::wkb_ndr);
+ str->q_append((uint32)Geometry::wkb_point);
str->q_append(x);
str->q_append(y);
return str;
@@ -325,16 +356,15 @@ String *Item_func_point::val_str(String *str)
String *Item_func_spatial_collection::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String arg_value;
uint i;
- null_value= 1;
-
str->length(0);
if (str->reserve(1 + 4 + 4, 512))
- return 0;
+ goto err;
- str->q_append((char) Geometry::wkbNDR);
+ str->q_append((char) Geometry::wkb_ndr);
str->q_append((uint32) coll_type);
str->q_append((uint32) arg_count);
@@ -342,19 +372,16 @@ String *Item_func_spatial_collection::val_str(String *str)
{
String *res= args[i]->val_str(&arg_value);
if (args[i]->null_value)
- goto ret;
+ goto err;
- if ( coll_type == Geometry::wkbGeometryCollection )
+ if (coll_type == Geometry::wkb_geometrycollection)
{
/*
- In the case of GeometryCollection we don't need
- any checkings for item types, so just copy them
- into target collection
+ In the case of GeometryCollection we don't need any checkings
+ for item types, so just copy them into target collection
*/
- if ((null_value= str->reserve(res->length(), 512)))
- goto ret;
-
- str->q_append(res->ptr(), res->length());
+ if (str->append(res->ptr(), res->length(), (uint32) 512))
+ goto err;
}
else
{
@@ -363,109 +390,101 @@ String *Item_func_spatial_collection::val_str(String *str)
const char *data= res->ptr() + 1;
/*
- In the case of named collection we must to
- check that items are of specific type, let's
- do this checking now
+ In the case of named collection we must to check that items
+ are of specific type, let's do this checking now
*/
if (len < 5)
- goto ret;
+ goto err;
wkb_type= (Geometry::wkbType) uint4korr(data);
data+= 4;
len-= 5;
if (wkb_type != item_type)
- goto ret;
+ goto err;
switch (coll_type) {
- case Geometry::wkbMultiPoint:
- case Geometry::wkbMultiLineString:
- case Geometry::wkbMultiPolygon:
- if (len < WKB_HEADER_SIZE)
- goto ret;
-
- data-= WKB_HEADER_SIZE;
- len+= WKB_HEADER_SIZE;
- if (str->reserve(len, 512))
- goto ret;
- str->q_append(data, len);
+ case Geometry::wkb_multipoint:
+ case Geometry::wkb_multilinestring:
+ case Geometry::wkb_multipolygon:
+ if (len < WKB_HEADER_SIZE ||
+ str->append(data-WKB_HEADER_SIZE, len+WKB_HEADER_SIZE, 512))
+ goto err;
break;
- case Geometry::wkbLineString:
- if (str->reserve(POINT_DATA_SIZE, 512))
- goto ret;
- str->q_append(data, POINT_DATA_SIZE);
+ case Geometry::wkb_linestring:
+ if (str->append(data, POINT_DATA_SIZE, 512))
+ goto err;
break;
-
- case Geometry::wkbPolygon:
+ case Geometry::wkb_polygon:
{
uint32 n_points;
double x1, y1, x2, y2;
+ const char *org_data= data;
if (len < 4 + 2 * POINT_DATA_SIZE)
- goto ret;
-
- uint32 llen= len;
- const char *ldata= data;
+ goto err;
n_points= uint4korr(data);
data+= 4;
float8get(x1, data);
- data+= 8;
+ data+= SIZEOF_STORED_DOUBLE;
float8get(y1, data);
- data+= 8;
+ data+= SIZEOF_STORED_DOUBLE;
data+= (n_points - 2) * POINT_DATA_SIZE;
float8get(x2, data);
- float8get(y2, data + 8);
-
- if ((x1 != x2) || (y1 != y2))
- goto ret;
+ float8get(y2, data + SIZEOF_STORED_DOUBLE);
- if (str->reserve(llen, 512))
- goto ret;
- str->q_append(ldata, llen);
+ if ((x1 != x2) || (y1 != y2) ||
+ str->append(org_data, len, 512))
+ goto err;
}
break;
default:
- goto ret;
+ goto err;
}
}
}
-
if (str->length() > current_thd->variables.max_allowed_packet)
- goto ret;
+ goto err;
null_value = 0;
+ return str;
-ret:
- return null_value ? 0 : str;
+err:
+ null_value= 1;
+ return 0;
}
+
/*
Functions for spatial relations
*/
longlong Item_func_spatial_rel::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res1= args[0]->val_str(&tmp_value1);
String *res2= args[1]->val_str(&tmp_value2);
- Geometry g1, g2;
+ Geometry_buffer buffer1, buffer2;
+ Geometry *g1, *g2;
MBR mbr1, mbr2;
-
- if ((null_value= (args[0]->null_value ||
- args[1]->null_value ||
- g1.create_from_wkb(res1->ptr() + SRID_SIZE,
- res1->length() - SRID_SIZE) ||
- g2.create_from_wkb(res2->ptr() + SRID_SIZE,
- res2->length() - SRID_SIZE) ||
- g1.get_mbr(&mbr1) ||
- g2.get_mbr(&mbr2))))
+ const char *dummy;
+
+ if ((null_value=
+ (args[0]->null_value ||
+ args[1]->null_value ||
+ !(g1= Geometry::create_from_wkb(&buffer1, res1->ptr() + SRID_SIZE,
+ res1->length() - SRID_SIZE)) ||
+ !(g2= Geometry::create_from_wkb(&buffer2, res2->ptr() + SRID_SIZE,
+ res2->length() - SRID_SIZE)) ||
+ g1->get_mbr(&mbr1, &dummy) ||
+ g2->get_mbr(&mbr2, &dummy))))
return 0;
- switch (spatial_rel)
- {
+ switch (spatial_rel) {
case SP_CONTAINS_FUNC:
return mbr1.contains(&mbr2);
case SP_WITHIN_FUNC:
@@ -490,37 +509,44 @@ longlong Item_func_spatial_rel::val_int()
return 0;
}
+
longlong Item_func_isempty::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String tmp;
null_value=0;
return args[0]->null_value ? 1 : 0;
}
+
longlong Item_func_issimple::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String tmp;
String *wkb=args[0]->val_str(&tmp);
- if ((null_value= (!wkb || args[0]->null_value )))
+ if ((null_value= (!wkb || args[0]->null_value)))
return 0;
/* TODO: Ramil or Holyfoot, add real IsSimple calculation */
return 0;
}
+
longlong Item_func_isclosed::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String tmp;
String *swkb= args[0]->val_str(&tmp);
- Geometry geom;
- int isclosed;
+ Geometry_buffer buffer;
+ Geometry *geom;
+ int isclosed= 0; // In case of error
null_value= (!swkb ||
args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom,is_closed) ||
- geom.is_closed(&isclosed));
+ !(geom=
+ Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)) ||
+ geom->is_closed(&isclosed));
return (longlong) isclosed;
}
@@ -529,129 +555,160 @@ longlong Item_func_isclosed::val_int()
Numerical functions
*/
+
longlong Item_func_dimension::val_int()
{
- uint32 dim;
+ DBUG_ASSERT(fixed == 1);
+ uint32 dim= 0; // In case of error
String *swkb= args[0]->val_str(&value);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
+ const char *dummy;
null_value= (!swkb ||
args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- geom.dimension(&dim));
+ !(geom= Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)) ||
+ geom->dimension(&dim, &dummy));
return (longlong) dim;
}
+
longlong Item_func_numinteriorring::val_int()
{
- uint32 num;
+ DBUG_ASSERT(fixed == 1);
+ uint32 num= 0; // In case of error
String *swkb= args[0]->val_str(&value);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, num_interior_ring) ||
- geom.num_interior_ring(&num));
+ !(geom= Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)) ||
+ geom->num_interior_ring(&num));
return (longlong) num;
}
+
longlong Item_func_numgeometries::val_int()
{
- uint32 num= 0;
+ DBUG_ASSERT(fixed == 1);
+ uint32 num= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, num_geometries) ||
- geom.num_geometries(&num));
+ !(geom= Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)) ||
+ geom->num_geometries(&num));
return (longlong) num;
}
+
longlong Item_func_numpoints::val_int()
{
- uint32 num;
+ DBUG_ASSERT(fixed == 1);
+ uint32 num= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
null_value= (!swkb ||
args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, num_points) ||
- geom.num_points(&num));
+ !(geom= Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)) ||
+ geom->num_points(&num));
return (longlong) num;
}
+
double Item_func_x::val()
{
- double res;
+ DBUG_ASSERT(fixed == 1);
+ double res= 0.0; // In case of errors
String *swkb= args[0]->val_str(&value);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, get_x) ||
- geom.get_x(&res));
+ !(geom= Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)) ||
+ geom->get_x(&res));
return res;
}
+
double Item_func_y::val()
{
- double res;
+ DBUG_ASSERT(fixed == 1);
+ double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, get_y) ||
- geom.get_y(&res));
+ !(geom= Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)) ||
+ geom->get_y(&res));
return res;
}
+
double Item_func_area::val()
{
- double res;
+ DBUG_ASSERT(fixed == 1);
+ double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
+ const char *dummy;
null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, area) ||
- geom.area(&res));
+ !(geom= Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)) ||
+ geom->area(&res, &dummy));
return res;
}
double Item_func_glength::val()
{
- double res;
+ DBUG_ASSERT(fixed == 1);
+ double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, length) ||
- geom.length(&res));
+ !(geom= Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)) ||
+ geom->length(&res));
return res;
}
longlong Item_func_srid::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *swkb= args[0]->val_str(&value);
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
+
+ null_value= !swkb ||
+ !(geom= Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE));
+ if (null_value)
+ return 0;
- null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE));
- uint32 res= uint4korr(swkb->ptr());
- return (longlong) res;
+ return (longlong) (uint4korr(swkb->ptr()));
}
#endif /*HAVE_SPATIAL*/
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index 545052807ec..a1f36130152 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -23,8 +23,6 @@
#pragma interface /* gcc class implementation */
#endif
-#define SRID_SIZE sizeof(uint32)
-
class Item_func_geometry_from_text: public Item_str_func
{
public:
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 7f847bd1d4e..c7e4bc0acf4 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -55,6 +55,7 @@ void Item_row::illegal_method_call(const char *method)
bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
null_value= 0;
maybe_null= 0;
Item **arg, **arg_end;
@@ -62,20 +63,23 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
{
if ((*arg)->fix_fields(thd, tabl, arg))
return 1;
- used_tables_cache |= (*arg)->used_tables();
- if (const_item_cache&= (*arg)->const_item() && !with_null)
+ // we can't assign 'item' before, because fix_fields() can change arg
+ Item *item= *arg;
+ used_tables_cache |= item->used_tables();
+ if (const_item_cache&= item->const_item() && !with_null)
{
- if ((*arg)->cols() > 1)
- with_null|= (*arg)->null_inside();
+ if (item->cols() > 1)
+ with_null|= item->null_inside();
else
{
- (*arg)->val_int();
- with_null|= (*arg)->null_value;
+ item->val_int();
+ with_null|= item->null_value;
}
}
- maybe_null|= (*arg)->maybe_null;
- with_sum_func= with_sum_func || (*arg)->with_sum_func;
+ maybe_null|= item->maybe_null;
+ with_sum_func= with_sum_func || item->with_sum_func;
}
+ fixed= 1;
return 0;
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 216df5c17d6..933995c1d22 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -60,6 +60,7 @@ uint nr_of_decimals(const char *str)
double Item_str_func::val()
{
+ DBUG_ASSERT(fixed == 1);
int err;
String *res;
res=val_str(&str_value);
@@ -69,15 +70,20 @@ double Item_str_func::val()
longlong Item_str_func::val_int()
{
+ DBUG_ASSERT(fixed == 1);
int err;
String *res;
res=val_str(&str_value);
- return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10,NULL,&err) : (longlong) 0;
+ return (res ?
+ my_strntoll(res->charset(), res->ptr(), res->length(), 10, NULL,
+ &err) :
+ (longlong) 0);
}
String *Item_func_md5::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String * sptr= args[0]->val_str(str);
if (sptr)
{
@@ -115,6 +121,7 @@ void Item_func_md5::fix_length_and_dec()
String *Item_func_sha::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String * sptr= args[0]->val_str(str);
if (sptr) /* If we got value different from NULL */
{
@@ -155,6 +162,7 @@ void Item_func_sha::fix_length_and_dec()
String *Item_func_aes_encrypt::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
char key_buff[80];
String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
String *sptr= args[0]->val_str(str); // String to encrypt
@@ -190,6 +198,7 @@ void Item_func_aes_encrypt::fix_length_and_dec()
String *Item_func_aes_decrypt::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
char key_buff[80];
String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
String *sptr, *key;
@@ -234,6 +243,7 @@ void Item_func_aes_decrypt::fix_length_and_dec()
String *Item_func_concat::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res,*res2,*use_as_buff;
uint i;
@@ -350,6 +360,7 @@ void Item_func_concat::fix_length_and_dec()
String *Item_func_des_encrypt::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
#ifdef HAVE_OPENSSL
DES_cblock ivec;
struct st_des_keyblock keyblock;
@@ -432,6 +443,7 @@ error:
String *Item_func_des_decrypt::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
#ifdef HAVE_OPENSSL
DES_key_schedule ks1, ks2, ks3;
DES_cblock ivec;
@@ -503,6 +515,7 @@ error:
String *Item_func_concat_ws::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
char tmp_str_buff[10];
String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
*sep_str, *res, *res2,*use_as_buff;
@@ -628,9 +641,11 @@ void Item_func_concat_ws::fix_length_and_dec()
max_length=separator->max_length*(arg_count-1);
for (uint i=0 ; i < arg_count ; i++)
{
+ DTCollation tmp(collation.collation, collation.derivation);
max_length+=args[i]->max_length;
if (collation.aggregate(args[i]->collation))
{
+ collation.set(tmp); // Restore the previous value
my_coll_agg_error(collation, args[i]->collation, func_name());
break;
}
@@ -668,6 +683,7 @@ void Item_func_concat_ws::print(String *str)
String *Item_func_reverse::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
char *ptr,*end;
@@ -725,6 +741,7 @@ void Item_func_reverse::fix_length_and_dec()
String *Item_func_replace::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res,*res2,*res3;
int offset;
uint from_length,to_length;
@@ -845,6 +862,7 @@ void Item_func_replace::fix_length_and_dec()
String *Item_func_insert::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res,*res2;
uint start,length;
@@ -892,6 +910,7 @@ void Item_func_insert::fix_length_and_dec()
String *Item_func_lcase::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res;
if (!(res=args[0]->val_str(str)))
{
@@ -907,6 +926,7 @@ String *Item_func_lcase::val_str(String *str)
String *Item_func_ucase::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res;
if (!(res=args[0]->val_str(str)))
{
@@ -922,6 +942,7 @@ String *Item_func_ucase::val_str(String *str)
String *Item_func_left::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
long length =(long) args[1]->val_int();
@@ -966,6 +987,7 @@ void Item_func_left::fix_length_and_dec()
String *Item_func_right::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
long length =(long) args[1]->val_int();
@@ -994,6 +1016,7 @@ void Item_func_right::fix_length_and_dec()
String *Item_func_substr::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
int32 start = (int32) args[1]->val_int();
int32 length = arg_count == 3 ? (int32) args[2]->val_int() : INT_MAX32;
@@ -1033,7 +1056,7 @@ void Item_func_substr::fix_length_and_dec()
}
if (arg_count == 3 && args[2]->const_item())
{
- int32 length= (int32) args[2]->val_int() * default_charset_info->mbmaxlen;
+ int32 length= (int32) args[2]->val_int() * collation.collation->mbmaxlen;
if (length <= 0)
max_length=0; /* purecov: inspected */
else
@@ -1053,6 +1076,7 @@ void Item_func_substr_index::fix_length_and_dec()
String *Item_func_substr_index::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
String *delimeter =args[1]->val_str(&tmp_value);
int32 count = (int32) args[2]->val_int();
@@ -1164,6 +1188,7 @@ String *Item_func_substr_index::val_str(String *str)
String *Item_func_ltrim::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
@@ -1202,6 +1227,7 @@ String *Item_func_ltrim::val_str(String *str)
String *Item_func_rtrim::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
@@ -1274,6 +1300,7 @@ String *Item_func_rtrim::val_str(String *str)
String *Item_func_trim::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
@@ -1346,6 +1373,7 @@ void Item_func_trim::fix_length_and_dec()
String *Item_func_password::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res= args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
@@ -1368,6 +1396,7 @@ char *Item_func_password::alloc(THD *thd, const char *password)
String *Item_func_old_password::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res= args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
@@ -1391,6 +1420,7 @@ char *Item_func_old_password::alloc(THD *thd, const char *password)
String *Item_func_encrypt::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
#ifdef HAVE_CRYPT
@@ -1435,6 +1465,7 @@ void Item_func_encode::fix_length_and_dec()
String *Item_func_encode::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res;
if (!(res=args[0]->val_str(str)))
{
@@ -1450,6 +1481,7 @@ String *Item_func_encode::val_str(String *str)
String *Item_func_decode::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res;
if (!(res=args[0]->val_str(str)))
{
@@ -1466,6 +1498,7 @@ String *Item_func_decode::val_str(String *str)
String *Item_func_database::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
THD *thd= current_thd;
if (!thd->db)
{
@@ -1481,6 +1514,7 @@ String *Item_func_database::val_str(String *str)
String *Item_func_user::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
THD *thd=current_thd;
CHARSET_INFO *cs= system_charset_info;
const char *host= thd->host_or_ip;
@@ -1531,6 +1565,7 @@ static char get_scode(CHARSET_INFO *cs,char *ptr)
String *Item_func_soundex::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
char last_ch,ch;
CHARSET_INFO *cs= collation.collation;
@@ -1591,6 +1626,7 @@ Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org)
String *Item_func_format::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
double nr =args[0]->val();
uint32 diff,length,str_length;
uint dec;
@@ -1661,6 +1697,7 @@ void Item_func_elt::fix_length_and_dec()
double Item_func_elt::val()
{
+ DBUG_ASSERT(fixed == 1);
uint tmp;
null_value=1;
if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
@@ -1673,6 +1710,7 @@ double Item_func_elt::val()
longlong Item_func_elt::val_int()
{
+ DBUG_ASSERT(fixed == 1);
uint tmp;
null_value=1;
if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
@@ -1686,6 +1724,7 @@ longlong Item_func_elt::val_int()
String *Item_func_elt::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
uint tmp;
null_value=1;
if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
@@ -1743,6 +1782,7 @@ void Item_func_make_set::update_used_tables()
String *Item_func_make_set::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
ulonglong bits;
bool first_found=0;
Item **ptr=args;
@@ -1808,6 +1848,7 @@ void Item_func_make_set::print(String *str)
String *Item_func_char::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
str->length(0);
for (uint i=0 ; i < arg_count ; i++)
{
@@ -1882,6 +1923,7 @@ void Item_func_repeat::fix_length_and_dec()
String *Item_func_repeat::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
uint length,tot_length;
char *to;
long count= (long) args[1]->val_int();
@@ -1944,6 +1986,7 @@ void Item_func_rpad::fix_length_and_dec()
String *Item_func_rpad::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
uint32 res_byte_length,res_char_length,pad_char_length,pad_byte_length;
char *to;
const char *ptr_pad;
@@ -2020,6 +2063,7 @@ void Item_func_lpad::fix_length_and_dec()
String *Item_func_lpad::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
uint32 res_char_length,pad_char_length;
ulong count= (long) args[1]->val_int(), byte_count;
String *res= args[0]->val_str(&tmp_value);
@@ -2069,6 +2113,7 @@ err:
String *Item_func_conv::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res= args[0]->val_str(str);
char *endptr,ans[65],*ptr;
longlong dec;
@@ -2097,6 +2142,7 @@ String *Item_func_conv::val_str(String *str)
String *Item_func_conv_charset::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *arg= args[0]->val_str(str);
if (!arg)
{
@@ -2124,6 +2170,7 @@ void Item_func_conv_charset::print(String *str)
String *Item_func_set_collation::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
str=args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
@@ -2183,6 +2230,7 @@ bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const
String *Item_func_charset::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
if ((null_value=(args[0]->null_value || !res->charset())))
@@ -2194,6 +2242,7 @@ String *Item_func_charset::val_str(String *str)
String *Item_func_collation::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
if ((null_value=(args[0]->null_value || !res->charset())))
@@ -2206,6 +2255,7 @@ String *Item_func_collation::val_str(String *str)
String *Item_func_hex::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if (args[0]->result_type() != STRING_RESULT)
{
/* Return hex of unsigned longlong value */
@@ -2231,7 +2281,7 @@ String *Item_func_hex::val_str(String *str)
null_value=0;
tmp_value.length(res->length()*2);
for (from=res->ptr(), end=from+res->length(), to= (char*) tmp_value.ptr();
- from != end ;
+ from < end ;
from++, to+=2)
{
uint tmp=(uint) (uchar) *from;
@@ -2241,6 +2291,49 @@ String *Item_func_hex::val_str(String *str)
return &tmp_value;
}
+inline int hexchar_to_int(char c)
+{
+ if (c <= '9' && c >= '0')
+ return c-'0';
+ c|=32;
+ if (c <= 'f' && c >= 'a')
+ return c-'a'+10;
+ return -1;
+}
+
+String *Item_func_unhex::val_str(String *str)
+{
+ DBUG_ASSERT(fixed == 1);
+ /* Convert given hex string to a binary string */
+ String *res= args[0]->val_str(str);
+ const char *from=res->ptr(), *end;
+ char *to;
+ int r;
+ if (!res || tmp_value.alloc((1+res->length())/2))
+ {
+ null_value=1;
+ return 0;
+ }
+ null_value=0;
+ tmp_value.length((1+res->length())/2);
+ to= (char*) tmp_value.ptr();
+ if (res->length() % 2)
+ {
+ *to++= r= hexchar_to_int(*from++);
+ if ((null_value= (r == -1)))
+ return 0;
+ }
+ for (end=res->ptr()+res->length(); from < end ; from+=2, to++)
+ {
+ *to= (r= hexchar_to_int(from[0])) << 4;
+ if ((null_value= (r == -1)))
+ return 0;
+ *to|= r= hexchar_to_int(from[1]);
+ if ((null_value= (r == -1)))
+ return 0;
+ }
+ return &tmp_value;
+}
void Item_func_binary::print(String *str)
{
@@ -2254,6 +2347,7 @@ void Item_func_binary::print(String *str)
String *Item_load_file::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *file_name;
File file;
MY_STAT stat_info;
@@ -2297,6 +2391,7 @@ err:
String* Item_func_export_set::val_str(String* str)
{
+ DBUG_ASSERT(fixed == 1);
ulonglong the_set = (ulonglong) args[0]->val_int();
String yes_buf, *yes;
yes = args[1]->val_str(&yes_buf);
@@ -2366,6 +2461,7 @@ void Item_func_export_set::fix_length_and_dec()
String* Item_func_inet_ntoa::val_str(String* str)
{
+ DBUG_ASSERT(fixed == 1);
uchar buf[8], *p;
ulonglong n = (ulonglong) args[0]->val_int();
char num[4];
@@ -2425,6 +2521,7 @@ String* Item_func_inet_ntoa::val_str(String* str)
String *Item_func_quote::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
/*
Bit mask that has 1 for set for the position of the following characters:
0, \, ' and ^Z
@@ -2499,6 +2596,7 @@ null:
longlong Item_func_uncompressed_length::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res= args[0]->val_str(&value);
if (!res)
{
@@ -2520,6 +2618,7 @@ longlong Item_func_uncompressed_length::val_int()
longlong Item_func_crc32::val_int()
{
+ DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
if (!res)
{
@@ -2535,6 +2634,7 @@ longlong Item_func_crc32::val_int()
String *Item_func_compress::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res= args[0]->val_str(str);
if (!res)
{
@@ -2592,6 +2692,7 @@ String *Item_func_compress::val_str(String *str)
String *Item_func_uncompress::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res= args[0]->val_str(str);
ulong new_size;
int err;
@@ -2654,14 +2755,6 @@ static const char hex[] = "0123456789abcdef";
#define UUID_VERSION 0x1000
#define UUID_VARIANT 0x8000
-static ulonglong get_uuid_time()
-{
- struct timeval tv;
- gettimeofday(&tv,NULL);
- return (ulonglong)tv.tv_sec*10000000 +
- (ulonglong)tv.tv_usec*10 + UUID_TIME_OFFSET + nanoseq;
-}
-
static void tohex(char *to, uint from, uint len)
{
to+= len;
@@ -2681,6 +2774,7 @@ static void set_clock_seq_str()
String *Item_func_uuid::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
char *s;
pthread_mutex_lock(&LOCK_uuid_generator);
if (! uuid_time) /* first UUID() call. initializing data */
@@ -2697,7 +2791,7 @@ String *Item_func_uuid::val_str(String *str)
randominit() here
*/
randominit(&uuid_rand, tmp + (ulong)current_thd, tmp + query_id);
- for (i=0; i < sizeof(mac); i++)
+ for (i=0; i < (int)sizeof(mac); i++)
mac[i]=(uchar)(my_rnd(&uuid_rand)*255);
}
s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1;
@@ -2710,7 +2804,7 @@ String *Item_func_uuid::val_str(String *str)
set_clock_seq_str();
}
- ulonglong tv=get_uuid_time();
+ ulonglong tv=my_getsystime() + UUID_TIME_OFFSET + nanoseq;
if (unlikely(tv < uuid_time))
set_clock_seq_str();
else
@@ -2720,7 +2814,14 @@ String *Item_func_uuid::val_str(String *str)
tv++;
}
else
- nanoseq=0;
+ {
+ if (nanoseq)
+ {
+ tv-=nanoseq;
+ nanoseq=0;
+ }
+ DBUG_ASSERT(tv > uuid_time);
+ }
uuid_time=tv;
pthread_mutex_unlock(&LOCK_uuid_generator);
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 7eb0750711f..22134733393 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -100,6 +100,7 @@ public:
void update_used_tables();
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
return (separator->fix_fields(thd, tlist, &separator) ||
separator->check_cols(1) ||
Item_func::fix_fields(thd, tlist, ref));
@@ -411,6 +412,7 @@ public:
String *val_str(String *str);
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
return (item->fix_fields(thd, tlist, &item) ||
item->check_cols(1) ||
Item_func::fix_fields(thd, tlist, ref));
@@ -500,10 +502,10 @@ public:
Item_func_conv(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
const char *func_name() const { return "conv"; }
String *val_str(String *);
- void fix_length_and_dec()
- {
+ void fix_length_and_dec()
+ {
collation.set(default_charset());
- decimals=0; max_length=64;
+ decimals=0; max_length=64;
}
};
@@ -515,14 +517,29 @@ public:
Item_func_hex(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "hex"; }
String *val_str(String *);
- void fix_length_and_dec()
- {
+ void fix_length_and_dec()
+ {
collation.set(default_charset());
decimals=0;
max_length=args[0]->max_length*2*collation.collation->mbmaxlen;
}
};
+class Item_func_unhex :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_unhex(Item *a) :Item_str_func(a) {}
+ const char *func_name() const { return "unhex"; }
+ String *val_str(String *);
+ void fix_length_and_dec()
+ {
+ collation.set(&my_charset_bin);
+ decimals=0;
+ max_length=(1+args[0]->max_length)/2;
+ }
+};
+
class Item_func_binary :public Item_str_func
{
@@ -530,16 +547,17 @@ public:
Item_func_binary(Item *a) :Item_str_func(a) {}
String *val_str(String *a)
{
+ DBUG_ASSERT(fixed == 1);
String *tmp=args[0]->val_str(a);
null_value=args[0]->null_value;
if (tmp)
tmp->set_charset(&my_charset_bin);
return tmp;
}
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- max_length=args[0]->max_length;
+ void fix_length_and_dec()
+ {
+ collation.set(&my_charset_bin);
+ max_length=args[0]->max_length;
}
void print(String *str);
};
@@ -553,7 +571,7 @@ public:
String *val_str(String *);
const char *func_name() const { return "load_file"; }
void fix_length_and_dec()
- {
+ {
collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
maybe_null=1;
max_length=MAX_BLOB_WIDTH;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index bfe41726f72..196b54141d1 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -102,6 +102,7 @@ Item_subselect::select_transformer(JOIN *join)
bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
stmt= thd->current_statement;
@@ -115,6 +116,8 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
{
if (substitution)
{
+ int ret= 0;
+
// did we changed top item of WHERE condition
if (unit->outer_select()->where == (*ref))
unit->outer_select()->where= substitution; // correct WHERE for PS
@@ -125,8 +128,9 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
engine->exclude();
substitution= 0;
fixed= 1;
- thd->where= "checking transformed subquery";
- int ret= (*ref)->fix_fields(thd, tables, ref);
+ thd->where= "checking transformed subquery";
+ if (!(*ref)->fixed)
+ ret= (*ref)->fix_fields(thd, tables, ref);
// We can't substitute aggregate functions (like (SELECT (max(i)))
if ((*ref)->with_sum_func)
{
@@ -198,6 +202,12 @@ bool Item_subselect::const_item() const
return const_item_cache;
}
+Item *Item_subselect::get_tmp_table_item(THD *thd)
+{
+ if (!with_sum_func && !const_item())
+ return new Item_field(result_field);
+ return copy_or_same(thd);
+}
void Item_subselect::update_used_tables()
{
@@ -390,6 +400,7 @@ void Item_singlerow_subselect::bring_value()
double Item_singlerow_subselect::val()
{
+ DBUG_ASSERT(fixed == 1);
if (!exec() && !value->null_value)
{
null_value= 0;
@@ -404,6 +415,7 @@ double Item_singlerow_subselect::val()
longlong Item_singlerow_subselect::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (!exec() && !value->null_value)
{
null_value= 0;
@@ -512,6 +524,7 @@ void Item_exists_subselect::fix_length_and_dec()
double Item_exists_subselect::val()
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -522,6 +535,7 @@ double Item_exists_subselect::val()
longlong Item_exists_subselect::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -532,6 +546,7 @@ longlong Item_exists_subselect::val_int()
String *Item_exists_subselect::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -543,6 +558,7 @@ String *Item_exists_subselect::val_str(String *str)
double Item_in_subselect::val()
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -556,6 +572,7 @@ double Item_in_subselect::val()
longlong Item_in_subselect::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -569,6 +586,7 @@ longlong Item_in_subselect::val_int()
String *Item_in_subselect::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -644,9 +662,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
*select_lex->ref_pointer_array= item;
select_lex->item_list.empty();
select_lex->item_list.push_back(item);
-
- if (item->fix_fields(thd, join->tables_list, &item))
- goto err;
+
+ // fix_fields call for 'item' will be made during new subquery fix_fields
subs= new Item_singlerow_subselect(select_lex);
}
@@ -734,9 +751,9 @@ Item_in_subselect::single_value_transformer(JOIN *join,
select_lex->ref_pointer_array[0]= select_lex->item_list.head();
if (select_lex->table_list.elements)
{
- Item *having= item, *isnull= item;
+ Item *having= item, *orig_item= item;
item= func->create(expr, item);
- if (!abort_on_null)
+ if (!abort_on_null && orig_item->maybe_null)
{
having= new Item_is_not_null_test(this, having);
/*
@@ -756,7 +773,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
}
select_lex->having_fix_field= 0;
item= new Item_cond_or(item,
- new Item_func_isnull(isnull));
+ new Item_func_isnull(orig_item));
}
item->name= (char *)in_additional_cond;
/*
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index d550cde64b7..e68c882ba3e 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -99,6 +99,7 @@ public:
bool const_item() const;
inline table_map get_used_tables_cache() { return used_tables_cache; }
inline bool get_const_item_cache() { return const_item_cache; }
+ Item *get_tmp_table_item(THD *thd);
void update_used_tables();
void print(String *str);
bool change_engine(subselect_engine *eng)
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 879c5f99ebd..807585f696d 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -137,6 +137,7 @@ bool Item_sum::walk (Item_processor processor, byte *argument)
String *
Item_sum_num::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
double nr=val();
if (null_value)
return 0;
@@ -148,6 +149,7 @@ Item_sum_num::val_str(String *str)
String *
Item_sum_int::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
longlong nr= val_int();
if (null_value)
return 0;
@@ -162,6 +164,7 @@ Item_sum_int::val_str(String *str)
bool
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
if (!thd->allow_sum_func)
{
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
@@ -191,17 +194,22 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bool
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
- Item *item=args[0];
+ DBUG_ASSERT(fixed == 0);
+ Item *item= args[0];
if (!thd->allow_sum_func)
{
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
return 1;
}
thd->allow_sum_func=0; // No included group funcs
+
+ // 'item' can be changed during fix_fields
if (!item->fixed &&
- item->fix_fields(thd, tables, args) || item->check_cols(1))
+ item->fix_fields(thd, tables, args) ||
+ (item= args[0])->check_cols(1))
return 1;
- hybrid_type=item->result_type();
+
+ hybrid_type= item->result_type();
if (hybrid_type == INT_RESULT)
{
cmp_charset= &my_charset_bin;
@@ -261,6 +269,7 @@ bool Item_sum_sum::add()
double Item_sum_sum::val()
{
+ DBUG_ASSERT(fixed == 1);
return sum;
}
@@ -292,6 +301,7 @@ bool Item_sum_count::add()
longlong Item_sum_count::val_int()
{
+ DBUG_ASSERT(fixed == 1);
return (longlong) count;
}
@@ -324,6 +334,7 @@ bool Item_sum_avg::add()
double Item_sum_avg::val()
{
+ DBUG_ASSERT(fixed == 1);
if (!count)
{
null_value=1;
@@ -340,6 +351,7 @@ double Item_sum_avg::val()
double Item_sum_std::val()
{
+ DBUG_ASSERT(fixed == 1);
double tmp= Item_sum_variance::val();
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
@@ -380,6 +392,7 @@ bool Item_sum_variance::add()
double Item_sum_variance::val()
{
+ DBUG_ASSERT(fixed == 1);
if (!count)
{
null_value=1;
@@ -435,6 +448,7 @@ void Item_sum_variance::update_field()
double Item_sum_hybrid::val()
{
+ DBUG_ASSERT(fixed == 1);
int err;
if (null_value)
return 0.0;
@@ -460,6 +474,7 @@ double Item_sum_hybrid::val()
longlong Item_sum_hybrid::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (null_value)
return 0;
if (hybrid_type == INT_RESULT)
@@ -471,6 +486,7 @@ longlong Item_sum_hybrid::val_int()
String *
Item_sum_hybrid::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if (null_value)
return 0;
switch (hybrid_type) {
@@ -605,6 +621,7 @@ bool Item_sum_max::add()
longlong Item_sum_bit::val_int()
{
+ DBUG_ASSERT(fixed == 1);
return (longlong) bits;
}
@@ -938,6 +955,7 @@ Item_avg_field::Item_avg_field(Item_sum_avg *item)
double Item_avg_field::val()
{
+ // fix_fields() never calls for this Item
double nr;
longlong count;
float8get(nr,field->ptr);
@@ -955,6 +973,7 @@ double Item_avg_field::val()
String *Item_avg_field::val_str(String *str)
{
+ // fix_fields() never calls for this Item
double nr=Item_avg_field::val();
if (null_value)
return 0;
@@ -969,6 +988,7 @@ Item_std_field::Item_std_field(Item_sum_std *item)
double Item_std_field::val()
{
+ // fix_fields() never calls for this Item
double tmp= Item_variance_field::val();
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
@@ -984,6 +1004,7 @@ Item_variance_field::Item_variance_field(Item_sum_variance *item)
double Item_variance_field::val()
{
+ // fix_fields() never calls for this Item
double sum,sum_sqr;
longlong count;
float8get(sum,field->ptr);
@@ -1003,6 +1024,7 @@ double Item_variance_field::val()
String *Item_variance_field::val_str(String *str)
{
+ // fix_fields() never calls for this Item
double nr=val();
if (null_value)
return 0;
@@ -1112,6 +1134,7 @@ void Item_sum_count_distinct::cleanup()
bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
if (Item_sum_num::fix_fields(thd, tables, ref))
return 1;
return 0;
@@ -1349,6 +1372,7 @@ bool Item_sum_count_distinct::add()
longlong Item_sum_count_distinct::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (!table) // Empty query
return LL(0);
if (use_tree)
@@ -1395,6 +1419,7 @@ Item *Item_sum_udf_float::copy_or_same(THD* thd)
double Item_sum_udf_float::val()
{
+ DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_sum_udf_float::val");
DBUG_PRINT("info",("result_type: %d arg_count: %d",
args[0]->result_type(), arg_count));
@@ -1403,6 +1428,7 @@ double Item_sum_udf_float::val()
String *Item_sum_udf_float::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
double nr=val();
if (null_value)
return 0; /* purecov: inspected */
@@ -1419,6 +1445,7 @@ Item *Item_sum_udf_int::copy_or_same(THD* thd)
longlong Item_sum_udf_int::val_int()
{
+ DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_sum_udf_int::val_int");
DBUG_PRINT("info",("result_type: %d arg_count: %d",
args[0]->result_type(), arg_count));
@@ -1428,6 +1455,7 @@ longlong Item_sum_udf_int::val_int()
String *Item_sum_udf_int::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
longlong nr=val_int();
if (null_value)
return 0;
@@ -1455,6 +1483,7 @@ Item *Item_sum_udf_str::copy_or_same(THD* thd)
String *Item_sum_udf_str::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_sum_udf_str::str");
String *res=udf.val_str(str,&str_value);
null_value = !res;
@@ -1675,6 +1704,7 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
void Item_func_group_concat::cleanup()
{
DBUG_ENTER("Item_func_group_concat::cleanup");
+ Item_sum::cleanup();
/*
Free table and tree if they belong to this item (if item have not pointer
to original item from which was made copy => it own its objects )
@@ -1790,6 +1820,7 @@ void Item_func_group_concat::reset_field()
bool
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
uint i; /* for loop variable */
if (!thd->allow_sum_func)
@@ -1957,6 +1988,7 @@ void Item_func_group_concat::make_unique()
String* Item_func_group_concat::val_str(String* str)
{
+ DBUG_ASSERT(fixed == 1);
if (null_value)
return 0;
if (tree_mode)
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 11c95100db5..1c31f1a9b70 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -88,7 +88,7 @@ public:
virtual void fix_length_and_dec() { maybe_null=1; null_value=1; }
virtual const char *func_name() const { return "?"; }
virtual Item *result_item(Field *field)
- { return new Item_field(field);}
+ { return new Item_field(field);}
table_map used_tables() const { return ~(table_map) 0; } /* Not used */
bool const_item() const { return 0; }
bool is_null() { return null_value; }
@@ -114,7 +114,8 @@ public:
Item_sum_num(List<Item> &list) :Item_sum(list) {}
Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {}
bool fix_fields(THD *, TABLE_LIST *, Item **);
- longlong val_int() { return (longlong) val(); } /* Real as default */
+ longlong val_int()
+ { DBUG_ASSERT(fixed == 1); return (longlong) val(); } /* Real as default */
String *val_str(String*str);
void reset_field();
};
@@ -126,7 +127,7 @@ public:
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
Item_sum_int(List<Item> &list) :Item_sum_num(list) {}
Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {}
- double val() { return (double) val_int(); }
+ double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
@@ -270,7 +271,7 @@ public:
Item_avg_field(Item_sum_avg *item);
enum Type type() const { return FIELD_AVG_ITEM; }
double val();
- longlong val_int() { return (longlong) val(); }
+ longlong val_int() { /* can't be fix_fields()ed */ return (longlong) val(); }
bool is_null() { (void) val_int(); return null_value; }
String *val_str(String*);
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
@@ -310,7 +311,7 @@ public:
Item_variance_field(Item_sum_variance *item);
enum Type type() const {return FIELD_VARIANCE_ITEM; }
double val();
- longlong val_int() { return (longlong) val(); }
+ longlong val_int() { /* can't be fix_fields()ed */ return (longlong) val(); }
String *val_str(String*);
bool is_null() { (void) val_int(); return null_value; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
@@ -533,6 +534,7 @@ public:
const char *func_name() const { return udf.name(); }
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
fixed= 1;
return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
}
@@ -554,7 +556,8 @@ class Item_sum_udf_float :public Item_udf_sum
:Item_udf_sum(udf_arg,list) {}
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
:Item_udf_sum(thd, item) {}
- longlong val_int() { return (longlong) Item_sum_udf_float::val(); }
+ longlong val_int()
+ { DBUG_ASSERT(fixed == 1); return (longlong) Item_sum_udf_float::val(); }
double val();
String *val_str(String*str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
@@ -571,7 +574,8 @@ public:
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
:Item_udf_sum(thd, item) {}
longlong val_int();
- double val() { return (double) Item_sum_udf_int::val_int(); }
+ double val()
+ { DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::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; }
@@ -616,7 +620,7 @@ class Item_sum_udf_float :public Item_sum_num
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
:Item_sum_num(thd, item) {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
- double val() { return 0.0; }
+ double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
void clear() {}
bool add() { return 0; }
void update_field() {}
@@ -631,8 +635,8 @@ public:
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
:Item_sum_num(thd, item) {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
- longlong val_int() { return 0; }
- double val() { return 0; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
+ double val() { DBUG_ASSERT(fixed == 1); return 0; }
void clear() {}
bool add() { return 0; }
void update_field() {}
@@ -646,9 +650,10 @@ public:
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
:Item_sum_num(thd, item) {}
- String *val_str(String *) { null_value=1; return 0; }
- double val() { null_value=1; return 0.0; }
- longlong val_int() { null_value=1; return 0; }
+ String *val_str(String *)
+ { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
+ double val() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec() { maybe_null=1; max_length=0; }
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 32fbe192d8f..1ac04cd9ff0 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -48,11 +48,6 @@ TYPELIB day_names_typelib=
{ array_elements(day_names)-1,"", day_names};
-enum date_time_format_types
-{
- TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
-};
-
/*
OPTIMIZATION TODO:
- Replace the switch with a function that should be called for each
@@ -128,6 +123,9 @@ static bool make_datetime(date_time_format_types format, TIME *ltime,
val String to decode
length Length of string
l_time Store result here
+ cached_timestamp_type
+ It uses to get an appropriate warning
+ in the case when the value is truncated.
RETURN
0 ok
@@ -135,7 +133,8 @@ static bool make_datetime(date_time_format_types format, TIME *ltime,
*/
static bool extract_date_time(DATE_TIME_FORMAT *format,
- const char *val, uint length, TIME *l_time)
+ const char *val, uint length, TIME *l_time,
+ timestamp_type cached_timestamp_type)
{
int weekday= 0, yearday= 0, daypart= 0;
int week_number= -1;
@@ -143,9 +142,11 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
int error= 0;
bool usa_time= 0;
bool sunday_first= 0;
+ int frac_part;
+ const char *val_begin= val;
const char *val_end= val + length;
const char *ptr= format->format.str;
- const char *end= ptr+ format->format.length;
+ const char *end= ptr + format->format.length;
DBUG_ENTER("extract_date_time");
bzero((char*) l_time, sizeof(*l_time));
@@ -235,7 +236,12 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
/* Second part */
case 'f':
tmp= (char*) val_end;
+ if (tmp - val > 6)
+ tmp= (char*) val + 6;
l_time->second_part= (int) my_strtoll10(val, &tmp, &error);
+ frac_part= 6 - (tmp - val);
+ if (frac_part > 0)
+ l_time->second_part*= (ulong) log_10_int[frac_part];
val= tmp;
break;
@@ -251,6 +257,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
(const uchar *) val, 2,
(const uchar *) "AM", 2))
goto err;
+ val+= 2;
break;
/* Exotic things */
@@ -281,6 +288,18 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
val= tmp;
break;
+ case '.':
+ while (my_ispunct(cs, *val) && val != val_end)
+ val++;
+ break;
+ case '@':
+ while (my_isalpha(cs, *val) && val != val_end)
+ val++;
+ break;
+ case '#':
+ while (my_isdigit(cs, *val) && val != val_end)
+ val++;
+ break;
default:
goto err;
}
@@ -348,6 +367,18 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
l_time->minute > 59 || l_time->second > 59)
goto err;
+ if (val != val_end)
+ {
+ do
+ {
+ if (!my_isspace(&my_charset_latin1,*val))
+ {
+ make_truncated_value_warning(current_thd, val_begin, length,
+ cached_timestamp_type);
+ break;
+ }
+ } while (++val != val_end);
+ }
DBUG_RETURN(0);
err:
@@ -584,16 +615,27 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
/*
-** Get a array of positive numbers from a string object.
-** Each number is separated by 1 non digit character
-** Return error if there is too many numbers.
-** If there is too few numbers, assume that the numbers are left out
-** from the high end. This allows one to give:
-** DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
+ Get a array of positive numbers from a string object.
+ Each number is separated by 1 non digit character
+ Return error if there is too many numbers.
+ If there is too few numbers, assume that the numbers are left out
+ from the high end. This allows one to give:
+ DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
+
+ SYNOPSIS
+ str: string value
+ length: length of str
+ cs: charset of str
+ values: array of results
+ count: count of elements in result array
+ transform_msec: if value is true we suppose
+ that the last part of string value is microseconds
+ and we should transform value to six digit value.
+ For example, '1.1' -> '1.100000'
*/
bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
- uint count, long *values)
+ uint count, long *values, bool transform_msec)
{
const char *end=str+length;
uint i;
@@ -603,8 +645,15 @@ bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
for (i=0 ; i < count ; i++)
{
long value;
+ const char *start= str;
for (value=0; str != end && my_isdigit(cs,*str) ; str++)
value=value*10L + (long) (*str - '0');
+ if (transform_msec && i == count - 1) // microseconds always last
+ {
+ long msec_length= 6 - (str - start);
+ if (msec_length > 0)
+ value*= (long) log_10_int[msec_length];
+ }
values[i]= value;
while (str != end && !my_isdigit(cs,*str))
str++;
@@ -623,6 +672,7 @@ bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
longlong Item_func_period_add::val_int()
{
+ DBUG_ASSERT(fixed == 1);
ulong period=(ulong) args[0]->val_int();
int months=(int) args[1]->val_int();
@@ -637,6 +687,7 @@ longlong Item_func_period_add::val_int()
longlong Item_func_period_diff::val_int()
{
+ DBUG_ASSERT(fixed == 1);
ulong period1=(ulong) args[0]->val_int();
ulong period2=(ulong) args[1]->val_int();
@@ -650,6 +701,7 @@ longlong Item_func_period_diff::val_int()
longlong Item_func_to_days::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
@@ -658,6 +710,7 @@ longlong Item_func_to_days::val_int()
longlong Item_func_dayofyear::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
@@ -667,6 +720,7 @@ longlong Item_func_dayofyear::val_int()
longlong Item_func_dayofmonth::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
(void) get_arg0_date(&ltime,1);
return (longlong) ltime.day;
@@ -674,6 +728,7 @@ longlong Item_func_dayofmonth::val_int()
longlong Item_func_month::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
(void) get_arg0_date(&ltime,1);
return (longlong) ltime.month;
@@ -682,6 +737,7 @@ longlong Item_func_month::val_int()
String* Item_func_monthname::val_str(String* str)
{
+ DBUG_ASSERT(fixed == 1);
const char *month_name;
uint month=(uint) Item_func_month::val_int();
@@ -701,6 +757,7 @@ String* Item_func_monthname::val_str(String* str)
longlong Item_func_quarter::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
(void) get_arg0_date(&ltime,1);
return (longlong) ((ltime.month+2)/3);
@@ -708,6 +765,7 @@ longlong Item_func_quarter::val_int()
longlong Item_func_hour::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
(void) get_arg0_time(&ltime);
return ltime.hour;
@@ -715,6 +773,7 @@ longlong Item_func_hour::val_int()
longlong Item_func_minute::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
(void) get_arg0_time(&ltime);
return ltime.minute;
@@ -723,6 +782,7 @@ longlong Item_func_minute::val_int()
longlong Item_func_second::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
(void) get_arg0_time(&ltime);
return ltime.second;
@@ -768,6 +828,7 @@ uint week_mode(uint mode)
longlong Item_func_week::val_int()
{
+ DBUG_ASSERT(fixed == 1);
uint year;
TIME ltime;
if (get_arg0_date(&ltime,0))
@@ -780,6 +841,7 @@ longlong Item_func_week::val_int()
longlong Item_func_yearweek::val_int()
{
+ DBUG_ASSERT(fixed == 1);
uint year,week;
TIME ltime;
if (get_arg0_date(&ltime,0))
@@ -795,6 +857,7 @@ longlong Item_func_yearweek::val_int()
longlong Item_func_weekday::val_int()
{
+ DBUG_ASSERT(fixed == 1);
ulong tmp_value=(ulong) args[0]->val_int();
if ((null_value=(args[0]->null_value || !tmp_value)))
return 0; /* purecov: inspected */
@@ -805,6 +868,7 @@ longlong Item_func_weekday::val_int()
String* Item_func_dayname::val_str(String* str)
{
+ DBUG_ASSERT(fixed == 1);
uint weekday=(uint) val_int(); // Always Item_func_daynr()
const char *name;
@@ -819,6 +883,7 @@ String* Item_func_dayname::val_str(String* str)
longlong Item_func_year::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
(void) get_arg0_date(&ltime,1);
return (longlong) ltime.year;
@@ -827,6 +892,7 @@ longlong Item_func_year::val_int()
longlong Item_func_unix_timestamp::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (arg_count == 0)
return (longlong) current_thd->query_start();
if (args[0]->type() == FIELD_ITEM)
@@ -846,6 +912,7 @@ longlong Item_func_unix_timestamp::val_int()
longlong Item_func_time_to_sec::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
longlong seconds;
(void) get_arg0_time(&ltime);
@@ -925,19 +992,19 @@ static bool get_interval_value(Item *args,interval_type int_type,
interval->second=value;
break;
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
- if (get_interval_info(str,length,cs,2,array))
+ if (get_interval_info(str,length,cs,2,array,0))
return (1);
interval->year=array[0];
interval->month=array[1];
break;
case INTERVAL_DAY_HOUR:
- if (get_interval_info(str,length,cs,2,array))
+ if (get_interval_info(str,length,cs,2,array,0))
return (1);
interval->day=array[0];
interval->hour=array[1];
break;
case INTERVAL_DAY_MICROSECOND:
- if (get_interval_info(str,length,cs,5,array))
+ if (get_interval_info(str,length,cs,5,array,1))
return (1);
interval->day=array[0];
interval->hour=array[1];
@@ -946,14 +1013,14 @@ static bool get_interval_value(Item *args,interval_type int_type,
interval->second_part=array[4];
break;
case INTERVAL_DAY_MINUTE:
- if (get_interval_info(str,length,cs,3,array))
+ if (get_interval_info(str,length,cs,3,array,0))
return (1);
interval->day=array[0];
interval->hour=array[1];
interval->minute=array[2];
break;
case INTERVAL_DAY_SECOND:
- if (get_interval_info(str,length,cs,4,array))
+ if (get_interval_info(str,length,cs,4,array,0))
return (1);
interval->day=array[0];
interval->hour=array[1];
@@ -961,7 +1028,7 @@ static bool get_interval_value(Item *args,interval_type int_type,
interval->second=array[3];
break;
case INTERVAL_HOUR_MICROSECOND:
- if (get_interval_info(str,length,cs,4,array))
+ if (get_interval_info(str,length,cs,4,array,1))
return (1);
interval->hour=array[0];
interval->minute=array[1];
@@ -969,33 +1036,33 @@ static bool get_interval_value(Item *args,interval_type int_type,
interval->second_part=array[3];
break;
case INTERVAL_HOUR_MINUTE:
- if (get_interval_info(str,length,cs,2,array))
+ if (get_interval_info(str,length,cs,2,array,0))
return (1);
interval->hour=array[0];
interval->minute=array[1];
break;
case INTERVAL_HOUR_SECOND:
- if (get_interval_info(str,length,cs,3,array))
+ if (get_interval_info(str,length,cs,3,array,0))
return (1);
interval->hour=array[0];
interval->minute=array[1];
interval->second=array[2];
break;
case INTERVAL_MINUTE_MICROSECOND:
- if (get_interval_info(str,length,cs,3,array))
+ if (get_interval_info(str,length,cs,3,array,1))
return (1);
interval->minute=array[0];
interval->second=array[1];
interval->second_part=array[2];
break;
case INTERVAL_MINUTE_SECOND:
- if (get_interval_info(str,length,cs,2,array))
+ if (get_interval_info(str,length,cs,2,array,0))
return (1);
interval->minute=array[0];
interval->second=array[1];
break;
case INTERVAL_SECOND_MICROSECOND:
- if (get_interval_info(str,length,cs,2,array))
+ if (get_interval_info(str,length,cs,2,array,1))
return (1);
interval->second=array[0];
interval->second_part=array[1];
@@ -1007,23 +1074,15 @@ static bool get_interval_value(Item *args,interval_type int_type,
String *Item_date::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
- ulong value=(ulong) val_int();
- if (null_value)
- return (String*) 0;
-
+ if (get_date(&ltime, TIME_FUZZY_DATE))
+ return (String *) 0;
if (str->alloc(11))
{
null_value= 1;
return (String *) 0;
}
-
- ltime.year= (value/10000L) % 10000;
- ltime.month= (value/100)%100;
- ltime.day= (value%100);
- ltime.neg= 0;
- ltime.time_type=TIMESTAMP_DATE;
-
make_date((DATE_TIME_FORMAT *) 0, &ltime, str);
return str;
}
@@ -1032,28 +1091,32 @@ String *Item_date::val_str(String *str)
int Item_date::save_in_field(Field *field, bool no_conversions)
{
TIME ltime;
- timestamp_type t_type=TIMESTAMP_DATETIME;
if (get_date(&ltime, TIME_FUZZY_DATE))
- {
- if (null_value)
- return set_field_to_null(field);
- t_type=TIMESTAMP_NONE; // Error
- }
+ return set_field_to_null(field);
field->set_notnull();
- field->store_time(&ltime,t_type);
+ field->store_time(&ltime, TIMESTAMP_DATE);
return 0;
}
-longlong Item_func_from_days::val_int()
+longlong Item_date::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ TIME ltime;
+ if (get_date(&ltime, TIME_FUZZY_DATE))
+ return 0;
+ return (longlong) (ltime.year*10000L+ltime.month*100+ltime.day);
+}
+
+
+bool Item_func_from_days::get_date(TIME *ltime, uint fuzzy_date)
{
longlong value=args[0]->val_int();
if ((null_value=args[0]->null_value))
- return 0; /* purecov: inspected */
-
- uint year,month,day;
- get_date_from_daynr((long) value,&year,&month,&day);
- return (longlong) (year*10000L+month*100+day);
+ return 1;
+ get_date_from_daynr((long) value, &ltime->year, &ltime->month, &ltime->day);
+ ltime->time_type= TIMESTAMP_DATE;
+ return 0;
}
@@ -1082,6 +1145,17 @@ void Item_func_curdate::fix_length_and_dec()
ltime.time_type=TIMESTAMP_DATE;
}
+String *Item_func_curdate::val_str(String *str)
+{
+ DBUG_ASSERT(fixed == 1);
+ if (str->alloc(11))
+ {
+ null_value= 1;
+ return (String *) 0;
+ }
+ make_date((DATE_TIME_FORMAT *) 0, &ltime, str);
+ return str;
+}
bool Item_func_curdate::get_date(TIME *res,
uint fuzzy_date __attribute__((unused)))
@@ -1112,7 +1186,8 @@ void Item_func_curdate_utc::store_now_in_tm(time_t now, struct tm *now_tm)
String *Item_func_curtime::val_str(String *str)
-{
+{
+ DBUG_ASSERT(fixed == 1);
str_value.set(buff, buff_length, &my_charset_bin);
return &str_value;
}
@@ -1162,6 +1237,7 @@ void Item_func_curtime_utc::store_now_in_tm(time_t now, struct tm *now_tm)
String *Item_func_now::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
str_value.set(buff,buff_length, &my_charset_bin);
return &str_value;
}
@@ -1237,6 +1313,7 @@ void Item_func_now_utc::store_now_in_tm(time_t now, struct tm *now_tm)
String *Item_func_sec_to_time::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
longlong seconds=(longlong) args[0]->val_int();
uint sec;
TIME ltime;
@@ -1267,6 +1344,7 @@ String *Item_func_sec_to_time::val_str(String *str)
longlong Item_func_sec_to_time::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong seconds=args[0]->val_int();
longlong sign=1;
if ((null_value=args[0]->null_value))
@@ -1375,6 +1453,7 @@ uint Item_func_date_format::format_length(const String *format)
String *Item_func_date_format::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *format;
TIME l_time;
uint size;
@@ -1424,6 +1503,7 @@ null_date:
String *Item_func_from_unixtime::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
struct tm tm_tmp,*start;
time_t tmp=(time_t) args[0]->val_int();
TIME ltime;
@@ -1456,6 +1536,7 @@ null_date:
longlong Item_func_from_unixtime::val_int()
{
+ DBUG_ASSERT(fixed == 1);
time_t tmp=(time_t) (ulong) args[0]->val_int();
if ((null_value=args[0]->null_value))
return 0;
@@ -1632,6 +1713,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
String *Item_date_add_interval::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
enum date_time_format_types format;
@@ -1655,6 +1737,7 @@ String *Item_date_add_interval::val_str(String *str)
longlong Item_date_add_interval::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
longlong date;
if (Item_date_add_interval::get_date(&ltime,0))
@@ -1724,6 +1807,7 @@ void Item_extract::fix_length_and_dec()
longlong Item_extract::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
long neg;
if (date_value)
@@ -1835,6 +1919,7 @@ void Item_char_typecast::print(String *str)
String *Item_char_typecast::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
String *res, *res1;
uint32 length;
@@ -1891,6 +1976,7 @@ void Item_char_typecast::fix_length_and_dec()
String *Item_datetime_typecast::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
if (!get_arg0_date(&ltime,1) &&
!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
@@ -1912,6 +1998,7 @@ bool Item_time_typecast::get_time(TIME *ltime)
String *Item_time_typecast::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
if (!get_arg0_time(&ltime) &&
@@ -1934,6 +2021,7 @@ bool Item_date_typecast::get_date(TIME *ltime, uint fuzzy_date)
String *Item_date_typecast::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
if (!get_arg0_date(&ltime,1) && !str->alloc(11))
@@ -1954,6 +2042,7 @@ String *Item_date_typecast::val_str(String *str)
String *Item_func_makedate::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
TIME l_time;
long daynr= (long) args[1]->val_int();
long yearnr= (long) args[0]->val_int();
@@ -2019,6 +2108,7 @@ void Item_func_add_time::fix_length_and_dec()
String *Item_func_add_time::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
TIME l_time1, l_time2, l_time3;
bool is_time= 0;
long microseconds, seconds, days= 0;
@@ -2140,6 +2230,7 @@ void Item_func_add_time::print(String *str)
String *Item_func_timediff::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
longlong seconds;
long microseconds;
long days;
@@ -2210,6 +2301,7 @@ null_date:
String *Item_func_maketime::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
long hour= (long) args[0]->val_int();
@@ -2248,6 +2340,7 @@ String *Item_func_maketime::val_str(String *str)
longlong Item_func_microsecond::val_int()
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
if (!get_arg0_time(&ltime))
return ltime.second_part;
@@ -2257,6 +2350,7 @@ longlong Item_func_microsecond::val_int()
String *Item_func_get_format::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
const char *format_name;
KNOWN_DATE_TIME_FORMAT *format;
String *val= args[0]->val_str(str);
@@ -2311,6 +2405,103 @@ void Item_func_get_format::print(String *str)
}
+/*
+ check_result_type(s, l) returns DATE/TIME type
+ according to format string
+
+ s: DATE/TIME format string
+ l: length of s
+ Result: date_time_format_types value:
+ DATE_TIME_MICROSECOND, DATE_TIME,
+ TIME_MICROSECOND, TIME_ONLY
+
+ We don't process day format's characters('D', 'd', 'e')
+ because day may be a member of all date/time types.
+ If only day format's character and no time part present
+ the result type is MYSQL_TYPE_DATE
+*/
+
+date_time_format_types check_result_type(const char *format, uint length)
+{
+ const char *time_part_frms= "HISThiklrs";
+ const char *date_part_frms= "MUYWabcjmuyw";
+ bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
+
+ const char *val= format;
+ const char *end= format + length;
+
+ for (; val != end && val != end; val++)
+ {
+ if (*val == '%' && val+1 != end)
+ {
+ val++;
+ if ((frac_second_used= (*val == 'f')) ||
+ (!time_part_used && strchr(time_part_frms, *val)))
+ time_part_used= 1;
+ else if (!date_part_used && strchr(date_part_frms, *val))
+ date_part_used= 1;
+ if (time_part_used && date_part_used && frac_second_used)
+ return DATE_TIME_MICROSECOND;
+ }
+ }
+
+ if (time_part_used)
+ {
+ if (date_part_used)
+ return DATE_TIME;
+ if (frac_second_used)
+ return TIME_MICROSECOND;
+ return TIME_ONLY;
+ }
+ return DATE_ONLY;
+}
+
+
+Field *Item_func_str_to_date::tmp_table_field(TABLE *t_arg)
+{
+ if (cached_field_type == MYSQL_TYPE_TIME)
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ if (cached_field_type == MYSQL_TYPE_DATE)
+ return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
+ if (cached_field_type == MYSQL_TYPE_DATETIME)
+ return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
+ return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin));
+}
+
+
+void Item_func_str_to_date::fix_length_and_dec()
+{
+ char format_buff[64];
+ String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format;
+ maybe_null= 1;
+ decimals=0;
+ cached_field_type= MYSQL_TYPE_STRING;
+ max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
+ cached_timestamp_type= TIMESTAMP_NONE;
+ if ((const_item= args[1]->const_item()))
+ {
+ format= args[1]->val_str(&format_str);
+ cached_format_type= check_result_type(format->ptr(), format->length());
+ switch (cached_format_type) {
+ case DATE_ONLY:
+ cached_timestamp_type= TIMESTAMP_DATE;
+ cached_field_type= MYSQL_TYPE_DATE;
+ max_length= MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
+ break;
+ case TIME_ONLY:
+ case TIME_MICROSECOND:
+ cached_timestamp_type= TIMESTAMP_TIME;
+ cached_field_type= MYSQL_TYPE_TIME;
+ max_length= MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
+ break;
+ default:
+ cached_timestamp_type= TIMESTAMP_DATETIME;
+ cached_field_type= MYSQL_TYPE_DATETIME;
+ break;
+ }
+ }
+}
+
bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
{
DATE_TIME_FORMAT date_time_format;
@@ -2328,8 +2519,18 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
date_time_format.format.str= (char*) format->ptr();
date_time_format.format.length= format->length();
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
- ltime))
+ ltime, cached_timestamp_type))
goto null_date;
+ if (cached_timestamp_type == TIMESTAMP_TIME && ltime->day)
+ {
+ /*
+ Day part for time type can be nonzero value and so
+ we should add hours from day part to hour part to
+ keep valid time value.
+ */
+ ltime->hour+= ltime->day*24;
+ ltime->day= 0;
+ }
return 0;
null_date:
@@ -2339,34 +2540,28 @@ null_date:
String *Item_func_str_to_date::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
TIME ltime;
if (Item_func_str_to_date::get_date(&ltime, TIME_FUZZY_DATE))
return 0;
- /*
- The following DATE_TIME should be done dynamicly based on the
- format string (wen it's a constant). For example, we should only return
- microseconds if there was an %f in the format
- */
- if (!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
+ if (!make_datetime((const_item ? cached_format_type :
+ (ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME)),
&ltime, str))
return str;
return 0;
}
-String *Item_func_last_day::val_str(String *str)
+bool Item_func_last_day::get_date(TIME *ltime, uint fuzzy_date)
{
- TIME ltime;
- if (!get_arg0_date(&ltime,0))
- {
- uint month_idx= ltime.month-1;
- ltime.day= days_in_month[month_idx];
- if ( month_idx == 1 && calc_days_in_year(ltime.year) == 366)
- ltime.day+= 1;
- if (!make_datetime(DATE_ONLY, &ltime, str))
- return str;
- }
+ if (get_arg0_date(ltime,fuzzy_date))
+ return 1;
+ uint month_idx= ltime->month-1;
+ ltime->day= days_in_month[month_idx];
+ if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366)
+ ltime->day= 29;
+ ltime->time_type= TIMESTAMP_DATE;
return 0;
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index a81b9f28d92..bfe7795500e 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -21,6 +21,11 @@
#pragma interface /* gcc class implementation */
#endif
+enum date_time_format_types
+{
+ TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
+};
+
class Item_func_period_add :public Item_int_func
{
public:
@@ -83,7 +88,8 @@ class Item_func_month :public Item_func
public:
Item_func_month(Item *a) :Item_func(a) {}
longlong val_int();
- double val() { return (double) Item_func_month::val_int(); }
+ double val()
+ { DBUG_ASSERT(fixed == 1); return (double) Item_func_month::val_int(); }
String *val_str(String *str)
{
str->set(val_int(), &my_charset_bin);
@@ -244,9 +250,10 @@ public:
Item_func_weekday(Item *a,bool type_arg)
:Item_func(a), odbc_type(type_arg) {}
longlong val_int();
- double val() { return (double) val_int(); }
+ double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String *str)
- {
+ {
+ DBUG_ASSERT(fixed == 1);
str->set(val_int(), &my_charset_bin);
return null_value ? 0 : str;
}
@@ -318,7 +325,8 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
String *val_str(String *str);
- double val() { return (double) val_int(); }
+ longlong val_int();
+ double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
const char *func_name() const { return "date"; }
void fix_length_and_dec()
{
@@ -360,8 +368,8 @@ public:
Item_func_curtime(Item *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
- double val() { return (double) value; }
- longlong val_int() { return value; }
+ double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
String *val_str(String *str);
void fix_length_and_dec();
Field *tmp_table_field(TABLE *t_arg)
@@ -406,7 +414,8 @@ class Item_func_curdate :public Item_date
public:
Item_func_curdate() :Item_date() {}
void set_result_from_tm(struct tm *now);
- longlong val_int() { return (value) ; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return (value) ; }
+ String *val_str(String *str);
void fix_length_and_dec();
bool get_date(TIME *res, uint fuzzy_date);
virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
@@ -443,8 +452,8 @@ public:
Item_func_now() :Item_date_func() {}
Item_func_now(Item *a) :Item_date_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
- double val() { return (double) value; }
- longlong val_int() { return value; }
+ double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
int save_in_field(Field *to, bool no_conversions);
String *val_str(String *str);
void fix_length_and_dec();
@@ -477,8 +486,8 @@ class Item_func_from_days :public Item_date
{
public:
Item_func_from_days(Item *a) :Item_date(a) {}
- longlong val_int();
const char *func_name() const { return "from_days"; }
+ bool get_date(TIME *res, uint fuzzy_date);
};
@@ -501,7 +510,11 @@ class Item_func_from_unixtime :public Item_date_func
{
public:
Item_func_from_unixtime(Item *a) :Item_date_func(a) {}
- double val() { return (double) Item_func_from_unixtime::val_int(); }
+ double val()
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (double) Item_func_from_unixtime::val_int();
+ }
longlong val_int();
String *val_str(String *str);
const char *func_name() const { return "from_unixtime"; }
@@ -519,7 +532,11 @@ class Item_func_sec_to_time :public Item_str_func
{
public:
Item_func_sec_to_time(Item *item) :Item_str_func(item) {}
- double val() { return (double) Item_func_sec_to_time::val_int(); }
+ double val()
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (double) Item_func_sec_to_time::val_int();
+ }
longlong val_int();
String *val_str(String *);
void fix_length_and_dec()
@@ -565,7 +582,7 @@ public:
const char *func_name() const { return "date_add_interval"; }
void fix_length_and_dec();
enum_field_types field_type() const { return cached_field_type; }
- double val() { return (double) val_int(); }
+ double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
longlong val_int();
bool get_date(TIME *res, uint fuzzy_date);
void print(String *str);
@@ -594,6 +611,7 @@ public:
Item_typecast(Item *a) :Item_str_func(a) {}
String *val_str(String *a)
{
+ DBUG_ASSERT(fixed == 1);
String *tmp=args[0]->val_str(a);
null_value=args[0]->null_value;
if (tmp)
@@ -610,6 +628,19 @@ public:
};
+class Item_typecast_maybe_null :public Item_typecast
+{
+public:
+ Item_typecast_maybe_null(Item *a) :Item_typecast(a) {}
+ void fix_length_and_dec()
+ {
+ collation.set(&my_charset_bin);
+ max_length=args[0]->max_length;
+ maybe_null= 1;
+ }
+};
+
+
class Item_char_typecast :public Item_typecast
{
int cast_length;
@@ -626,10 +657,10 @@ public:
};
-class Item_date_typecast :public Item_typecast
+class Item_date_typecast :public Item_typecast_maybe_null
{
public:
- Item_date_typecast(Item *a) :Item_typecast(a) {}
+ Item_date_typecast(Item *a) :Item_typecast_maybe_null(a) {}
String *val_str(String *str);
bool get_date(TIME *ltime, uint fuzzy_date);
const char *cast_type() const { return "date"; }
@@ -641,10 +672,10 @@ public:
};
-class Item_time_typecast :public Item_typecast
+class Item_time_typecast :public Item_typecast_maybe_null
{
public:
- Item_time_typecast(Item *a) :Item_typecast(a) {}
+ Item_time_typecast(Item *a) :Item_typecast_maybe_null(a) {}
String *val_str(String *str);
bool get_time(TIME *ltime);
const char *cast_type() const { return "time"; }
@@ -656,10 +687,10 @@ public:
};
-class Item_datetime_typecast :public Item_typecast
+class Item_datetime_typecast :public Item_typecast_maybe_null
{
public:
- Item_datetime_typecast(Item *a) :Item_typecast(a) {}
+ Item_datetime_typecast(Item *a) :Item_typecast_maybe_null(a) {}
String *val_str(String *str);
const char *cast_type() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
@@ -793,37 +824,29 @@ public:
};
-class Item_func_str_to_date :public Item_date_func
+class Item_func_str_to_date :public Item_str_func
{
+ enum_field_types cached_field_type;
+ date_time_format_types cached_format_type;
+ timestamp_type cached_timestamp_type;
+ bool const_item;
public:
Item_func_str_to_date(Item *a, Item *b)
- :Item_date_func(a, b)
+ :Item_str_func(a, b)
{}
String *val_str(String *str);
bool get_date(TIME *ltime, uint fuzzy_date);
const char *func_name() const { return "str_to_date"; }
- void fix_length_and_dec()
- {
- maybe_null= 1;
- decimals=0;
- max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
- }
+ enum_field_types field_type() const { return cached_field_type; }
+ void fix_length_and_dec();
+ Field *tmp_table_field(TABLE *t_arg);
};
-class Item_func_last_day :public Item_str_func
+
+class Item_func_last_day :public Item_date
{
public:
- Item_func_last_day(Item *a) :Item_str_func(a) {}
- String *val_str(String *str);
+ Item_func_last_day(Item *a) :Item_date(a) {}
const char *func_name() const { return "last_day"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
- void fix_length_and_dec()
- {
- decimals=0;
- max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
- }
- Field *tmp_table_field(TABLE *t_arg)
- {
- return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
- }
+ bool get_date(TIME *res, uint fuzzy_date);
};
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index 47f967b52c6..5582537bdbb 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -27,7 +27,7 @@ class Item_func_unique_users :public Item_real_func
public:
Item_func_unique_users(Item *name_arg,int start,int end,List<Item> &list)
:Item_real_func(list) {}
- double val() { return 0.0; }
+ double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
void fix_length_and_dec() { decimals=0; max_length=6; }
void print(String *str) { str->append("0.0", 3); }
};
@@ -40,7 +40,7 @@ public:
:Item_sum_num(item_arg) {}
Item_sum_unique_users(THD *thd, Item_sum_unique_users *item)
:Item_sum_num(thd, item) {}
- double val() { return 0.0; }
+ double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
void clear() {}
bool add() { return 0; }
@@ -48,6 +48,7 @@ public:
void update_field() {}
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
fixed= 1;
return 0;
}
diff --git a/sql/lex.h b/sql/lex.h
index 9cdb1067d91..3b32d2bcd3b 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -671,6 +671,7 @@ static SYMBOL sql_functions[] = {
{ "UCASE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "UNCOMPRESS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompress)},
{ "UNCOMPRESSED_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompressed_length)},
+ { "UNHEX", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_unhex)},
{ "UNIQUE_USERS", SYM(UNIQUE_USERS)},
{ "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP)},
{ "UPPER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
diff --git a/sql/lex_symbol.h b/sql/lex_symbol.h
index d1d30a73669..3074a489b6a 100644
--- a/sql/lex_symbol.h
+++ b/sql/lex_symbol.h
@@ -37,4 +37,13 @@ typedef struct st_lex_symbol
uint length;
} LEX_SYMBOL;
+typedef struct st_sym_group {
+ const char *name;
+ const char *needed_define;
+} SYM_GROUP;
+
+extern SYM_GROUP sym_group_common;
+extern SYM_GROUP sym_group_geom;
+extern SYM_GROUP sym_group_rtree;
+
#endif /* _lex_symbol_h */
diff --git a/sql/lock.cc b/sql/lock.cc
index 29795415720..171c880db3e 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -495,14 +495,17 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
char key[MAX_DBKEY_LENGTH];
- char *db= table_list->db ? table_list->db : (thd->db ? thd->db : (char*) "");
+ char *db= table_list->db;
uint key_length;
DBUG_ENTER("lock_table_name");
+ DBUG_PRINT("enter",("db: %s name: %s", db, table_list->real_name));
+
safe_mutex_assert_owner(&LOCK_open);
key_length=(uint) (strmov(strmov(key,db)+1,table_list->real_name)
-key)+ 1;
+
/* Only insert the table if we haven't insert it already */
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
table ;
@@ -534,6 +537,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
DBUG_RETURN(0);
}
+
void unlock_table_name(THD *thd, TABLE_LIST *table_list)
{
if (table_list->table)
@@ -543,6 +547,7 @@ void unlock_table_name(THD *thd, TABLE_LIST *table_list)
}
}
+
static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
{
for (; table_list ; table_list=table_list->next)
diff --git a/sql/log_event.cc b/sql/log_event.cc
index a128b5809b2..742cf6a1a82 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -56,11 +56,21 @@ static void pretty_print_str(FILE* file, char* str, int len)
#endif /* MYSQL_CLIENT */
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+
+static void clear_all_errors(THD *thd, struct st_relay_log_info *rli)
+{
+ thd->query_error = 0;
+ thd->clear_error();
+ *rli->last_slave_error = 0;
+ rli->last_slave_errno = 0;
+}
+
+
/*
- ignored_error_code()
+ Ignore error code specified on command line
*/
-#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
inline int ignored_error_code(int err_code)
{
return ((err_code == ER_SLAVE_IGNORED_TABLE) ||
@@ -843,7 +853,9 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans),
data_buf(0), query(query_arg),
db(thd_arg->db), q_len((uint32) query_length),
- error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
+ error_code(thd_arg->killed ?
+ ((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ?
+ 0 : ER_SERVER_SHUTDOWN) : thd_arg->net.last_errno),
thread_id(thd_arg->thread_id),
/* save the original thread id; we already know the server id */
slave_proxy_id(thd_arg->variables.pseudo_thread_id)
@@ -944,17 +956,15 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
thd->db= (char*) rewrite_db(db);
/*
- InnoDB internally stores the master log position it has executed so far,
- i.e. the position just after the COMMIT event.
- When InnoDB will want to store, the positions in rli won't have
- been updated yet, so group_master_log_* will point to old BEGIN
- and event_master_log* will point to the beginning of current COMMIT.
- So the position to store is event_master_log_pos + event_len
- since we must store the pos of the END of the current log event (COMMIT).
+ InnoDB internally stores the master log position it has processed so far;
+ position to store is of the END of the current log event.
*/
- rli->event_len= get_event_len();
- thd->query_error= 0; // clear error
- thd->clear_error();
+#if MYSQL_VERSION_ID < 50000
+ rli->future_group_master_log_pos= log_pos + get_event_len();
+#else
+ rli->future_group_master_log_pos= log_pos;
+#endif
+ clear_all_errors(thd, rli);
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
@@ -966,75 +976,85 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->variables.pseudo_thread_id= thread_id; // for temp tables
- /*
- Sanity check to make sure the master did not get a really bad
- error on the query.
- */
- if (ignored_error_code((expected_error = error_code)) ||
+ mysql_log.write(thd,COM_QUERY,"%s",thd->query);
+ DBUG_PRINT("query",("%s",thd->query));
+ if (ignored_error_code((expected_error= error_code)) ||
!check_expected_error(thd,rli,expected_error))
- {
- mysql_log.write(thd,COM_QUERY,"%s",thd->query);
- DBUG_PRINT("query",("%s",thd->query));
mysql_parse(thd, thd->query, q_len);
-
+ else
+ {
/*
- If we expected a non-zero error code, and we don't get the same error
- code, and none of them should be ignored.
+ The query got a really bad error on the master (thread killed etc),
+ which could be inconsistent. Parse it to test the table names: if the
+ replicate-*-do|ignore-table rules say "this query must be ignored" then
+ we exit gracefully; otherwise we warn about the bad error and tell DBA
+ to check/fix it.
*/
- DBUG_PRINT("info",("expected_error: %d last_errno: %d",
- expected_error, thd->net.last_errno));
- if ((expected_error != (actual_error= thd->net.last_errno)) &&
- expected_error &&
- !ignored_error_code(actual_error) &&
- !ignored_error_code(expected_error))
+ if (mysql_test_parse_for_slave(thd, thd->query, q_len))
+ clear_all_errors(thd, rli); /* Can ignore query */
+ else
{
- slave_print_error(rli, 0,
+ slave_print_error(rli,expected_error,
"\
+Query '%s' partially completed on the master (error on master: %d) \
+and was aborted. There is a chance that your master is inconsistent at this \
+point. If you are sure that your master is ok, run this query manually on the \
+slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; \
+START SLAVE; .", thd->query, expected_error);
+ thd->query_error= 1;
+ }
+ goto end;
+ }
+
+ /*
+ If we expected a non-zero error code, and we don't get the same error
+ code, and none of them should be ignored.
+ */
+ DBUG_PRINT("info",("expected_error: %d last_errno: %d",
+ expected_error, thd->net.last_errno));
+ if ((expected_error != (actual_error= thd->net.last_errno)) &&
+ expected_error &&
+ !ignored_error_code(actual_error) &&
+ !ignored_error_code(expected_error))
+ {
+ slave_print_error(rli, 0,
+ "\
Query '%s' caused different errors on master and slave. \
Error on master: '%s' (%d), Error on slave: '%s' (%d). \
Default database: '%s'",
- query,
- ER_SAFE(expected_error),
- expected_error,
- actual_error ? thd->net.last_error: "no error",
- actual_error,
- print_slave_db_safe(db));
- thd->query_error= 1;
- }
- /*
- If we get the same error code as expected, or they should be ignored.
- */
- else if (expected_error == actual_error ||
- ignored_error_code(actual_error))
- {
- DBUG_PRINT("info",("error ignored"));
- thd->query_error= 0;
- thd->clear_error();
- *rli->last_slave_error = 0;
- rli->last_slave_errno = 0;
- }
- /*
- Other cases: mostly we expected no error and get one.
- */
- else if (thd->query_error || thd->is_fatal_error)
- {
- slave_print_error(rli,actual_error,
- "Error '%s' on query '%s'. Default database: '%s'",
- (actual_error ? thd->net.last_error :
- "unexpected success or fatal error"),
- query,
- print_slave_db_safe(db));
- thd->query_error= 1;
- }
- }
- /*
- End of sanity check. If the test was wrong, the query got a really bad
- error on the master, which could be inconsistent, abort and tell DBA to
- check/fix it. check_expected_error() already printed the message to
- stderr and rli, and set thd->query_error to 1.
+ query,
+ ER_SAFE(expected_error),
+ expected_error,
+ actual_error ? thd->net.last_error: "no error",
+ actual_error,
+ print_slave_db_safe(db));
+ thd->query_error= 1;
+ }
+ /*
+ If we get the same error code as expected, or they should be ignored.
+ */
+ else if (expected_error == actual_error ||
+ ignored_error_code(actual_error))
+ {
+ DBUG_PRINT("info",("error ignored"));
+ clear_all_errors(thd, rli);
+ }
+ /*
+ Other cases: mostly we expected no error and get one.
*/
+ else if (thd->query_error || thd->is_fatal_error)
+ {
+ slave_print_error(rli,actual_error,
+ "Error '%s' on query '%s'. Default database: '%s'",
+ (actual_error ? thd->net.last_error :
+ "unexpected success or fatal error"),
+ query,
+ print_slave_db_safe(db));
+ thd->query_error= 1;
+ }
} /* End of if (db_ok(... */
+end:
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->db= 0; // prevent db from being freed
thd->query= 0; // just to be sure
@@ -1165,7 +1185,7 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli)
{
slave_print_error(rli, 0, "\
Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. \
-Probably cause is that the master died while writing the transaction to it's \
+A probable cause is that the master died while writing the transaction to its \
binary log.");
return(1);
}
@@ -1643,7 +1663,15 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
DBUG_ASSERT(thd->query == 0);
thd->query= 0; // Should not be needed
thd->query_error= 0;
- thd->clear_error();
+ clear_all_errors(thd, rli);
+ if (!use_rli_only_for_errors)
+ {
+#if MYSQL_VERSION_ID < 50000
+ rli->future_group_master_log_pos= log_pos + get_event_len();
+#else
+ rli->future_group_master_log_pos= log_pos;
+#endif
+ }
/*
We test replicate_*_db rules. Note that we have already prepared the file
@@ -2344,6 +2372,10 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
}
}
Item_func_set_user_var e(user_var_name, it);
+ /*
+ Item_func_set_user_var can't substitute something else on its place =>
+ 0 can be passed as last argument (reference on item)
+ */
e.fix_fields(thd, 0, 0);
e.update_hash(val, val_len, type, charset, DERIVATION_NONE);
free_root(&thd->mem_root,0);
@@ -2638,7 +2670,7 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len,
We must make copy of 'buf' as this event may have to live over a
rotate log entry when used in mysqlbinlog
*/
- if (!(event_buf= my_memdup(buf, len, MYF(MY_WME))) ||
+ if (!(event_buf= my_memdup((byte*) buf, len, MYF(MY_WME))) ||
(copy_log_event(event_buf, len, old_format)))
DBUG_VOID_RETURN;
@@ -3103,6 +3135,14 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
lev->exec_event is the place where the table is loaded (it calls
mysql_load()).
*/
+
+#if MYSQL_VERSION_ID < 40100
+ rli->future_master_log_pos= log_pos + get_event_len();
+#elif MYSQL_VERSION_ID < 50000
+ rli->future_group_master_log_pos= log_pos + get_event_len();
+#else
+ rli->future_group_master_log_pos= log_pos;
+#endif
if (lev->exec_event(0,rli,1))
{
/*
diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc
index b7e2a803e42..71c8d588de7 100644
--- a/sql/mf_iocache.cc
+++ b/sql/mf_iocache.cc
@@ -30,14 +30,8 @@
flush_io_cache().
*/
-#define MAP_TO_USE_RAID
#include "mysql_priv.h"
#ifdef HAVE_REPLICATION
-#ifdef HAVE_AIOWAIT
-#include <mysys_err.h>
-#include <errno.h>
-static void my_aiowait(my_aio_result *result);
-#endif
extern "C" {
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 535c1cb16be..126675a6e46 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -64,14 +64,6 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1))
#define all_bits_set(A,B) ((A) & (B) != (B))
-#ifndef LL
-#ifdef HAVE_LONG_LONG
-#define LL(A) A ## LL
-#else
-#define LL(A) A ## L
-#endif
-#endif
-
extern CHARSET_INFO *system_charset_info, *files_charset_info ;
extern CHARSET_INFO *national_charset_info, *table_alias_charset;
@@ -415,6 +407,7 @@ int quick_rm_table(enum db_type base,const char *db,
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
bool mysql_change_db(THD *thd,const char *name);
void mysql_parse(THD *thd,char *inBuf,uint length);
+bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
bool is_update_query(enum enum_sql_command command);
bool alloc_query(THD *thd, char *packet, ulong packet_length);
void mysql_init_select(LEX *lex);
@@ -440,7 +433,7 @@ bool check_stack_overrun(THD *thd,char *dummy);
#define check_stack_overrun(A, B) 0
#endif
-void table_cache_init(void);
+bool table_cache_init(void);
void table_cache_free(void);
uint cached_tables(void);
void kill_mysql(void);
@@ -620,14 +613,13 @@ int mysqld_show_column_types(THD *thd);
int mysqld_help (THD *thd, const char *text);
/* sql_prepare.cc */
-bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
-void mysql_stmt_execute(THD *thd, char *packet);
+void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
+void mysql_stmt_execute(THD *thd, char *packet, uint packet_length);
void mysql_stmt_free(THD *thd, char *packet);
void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter);
-void setup_param_functions(Item_param *param, uchar param_type);
/* sql_error.cc */
MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
@@ -760,6 +752,9 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
/* mysqld.cc */
extern void yyerror(const char*);
+/* item_func.cc */
+extern bool check_reserved_words(LEX_STRING *name);
+
/* strfunc.cc */
ulonglong find_set(TYPELIB *typelib,const char *x, uint length,
char **err_pos, uint *err_len, bool *set_warning);
@@ -800,6 +795,7 @@ 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 double log_10[32];
+extern ulonglong log_10_int[20];
extern ulonglong keybuff_size;
extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables;
extern ulong created_tmp_tables, created_tmp_disk_tables, bytes_sent;
@@ -823,7 +819,7 @@ extern ulong ha_read_rnd_count, ha_read_rnd_next_count;
extern ulong ha_commit_count, ha_rollback_count,table_cache_size;
extern ulong max_connections,max_connect_errors, connect_timeout;
extern ulong slave_net_timeout;
-extern ulong max_insert_delayed_threads, max_user_connections;
+extern ulong max_user_connections;
extern ulong long_query_count, what_to_log,flush_time;
extern ulong query_buff_size, thread_stack,thread_stack_min;
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
@@ -846,7 +842,7 @@ 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;
extern my_bool opt_slave_compressed_protocol, use_temp_pool;
-extern my_bool opt_readonly;
+extern my_bool opt_readonly, lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm;
extern my_bool opt_secure_auth;
extern char *shared_memory_base_name, *mysqld_unix_port;
@@ -959,6 +955,8 @@ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
void localtime_to_TIME(TIME *to, struct tm *from);
void calc_time_from_sec(TIME *to, long seconds, long microseconds);
+void make_truncated_value_warning(THD *thd, const char *str_val,
+ uint str_length, timestamp_type time_type);
extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type,
const char *format_str,
uint format_length);
@@ -1127,12 +1125,3 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
table->map= (table_map) 1 << tablenr;
table->force_index= table_list->force_index;
}
-
-typedef struct st_sym_group {
- const char *name;
- const char *needed_define;
-} SYM_GROUP;
-
-extern SYM_GROUP sym_group_common;
-extern SYM_GROUP sym_group_geom;
-extern SYM_GROUP sym_group_rtree;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 5071cfaff6b..525f3db3aff 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -247,6 +247,7 @@ arg_cmp_func Arg_comparator::comparator_matrix[4][2] =
bool opt_log, opt_update_log, opt_bin_log, opt_slow_log;
bool opt_error_log= IF_WIN(1,0);
bool opt_disable_networking=0, opt_skip_show_db=0;
+bool lower_case_table_names_used= 0;
bool server_id_supplied = 0;
bool opt_endinfo,using_udf_functions, locked_in_memory;
bool opt_using_transactions, using_update_log;
@@ -266,6 +267,7 @@ my_bool opt_sync_bdb_logs, opt_sync_frm;
my_bool opt_secure_auth= 0;
my_bool opt_short_log_format= 0;
my_bool opt_log_queries_not_using_indexes= 0;
+my_bool lower_case_file_system= 0;
volatile bool mqh_used = 0;
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
@@ -295,7 +297,7 @@ ulong select_range_check_count, select_range_count, select_scan_count;
ulong select_full_range_join_count,select_full_join_count;
ulong specialflag=0,opened_tables=0,created_tmp_tables=0,
created_tmp_disk_tables=0;
-ulong max_connections,max_insert_delayed_threads,max_used_connections,
+ulong max_connections,max_used_connections,
max_connect_errors, max_user_connections = 0;
ulong thread_id=1L,current_pid;
ulong slow_launch_threads = 0;
@@ -305,6 +307,14 @@ ulong my_bind_addr; /* the address we bind to */
volatile ulong cached_thread_count= 0;
double log_10[32]; /* 10 potences */
+ulonglong log_10_int[20]=
+{
+ 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL,
+ ULL(100000000), ULL(1000000000), ULL(10000000000), ULL(100000000000),
+ ULL(1000000000000), ULL(10000000000000), ULL(100000000000000),
+ ULL(1000000000000000), ULL(10000000000000000), ULL(100000000000000000),
+ ULL(1000000000000000000), ULL(10000000000000000000)
+};
time_t start_time;
@@ -1049,8 +1059,8 @@ static void set_user(const char *user)
{
/* Don't give a warning, if real user is same as given with --user */
struct passwd *user_info= getpwnam(user);
-
- if (!user_info || user_id != user_info->pw_uid)
+ if ((!user_info || user_id != user_info->pw_uid) &&
+ global_system_variables.log_warnings)
fprintf(stderr,
"Warning: One can only use the --user switch if running as root\n");
}
@@ -1187,7 +1197,7 @@ static void server_init(void)
pipe_name[sizeof(pipe_name)-1]= 0; /* Safety if too long string */
strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\",
- unix_socket, NullS);
+ mysql_unix_port, NullS);
bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
@@ -1745,7 +1755,8 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
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+10);
+ init_thr_alarm(max_connections +
+ global_system_variables.max_insert_delayed_threads + 10);
#if SIGINT != THR_KILL_SIGNAL
if (test_flags & TEST_SIGINT)
{
@@ -2093,10 +2104,11 @@ static int init_common_variables(const char *conf_file_name, int argc,
strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
#ifndef DBUG_OFF
- strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
-#else
- strmov(strend(server_version),MYSQL_SERVER_SUFFIX);
+ if (*(MYSQL_SERVER_SUFFIX))
+ strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
+ else
#endif
+ strmov(strend(server_version),MYSQL_SERVER_SUFFIX);
load_defaults(conf_file_name, groups, &argc, &argv);
defaults_argv=argv;
@@ -2124,10 +2136,11 @@ static int init_common_variables(const char *conf_file_name, int argc,
DBUG_PRINT("warning",
("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld",
files, max_connections, table_cache_size));
- sql_print_error("Warning: Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld",
+ if (global_system_variables.log_warnings)
+ sql_print_error("Warning: Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld",
files, max_connections, table_cache_size);
}
- else
+ else if (global_system_variables.log_warnings)
sql_print_error("Warning: Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files);
}
open_files_limit= files;
@@ -2176,10 +2189,14 @@ static int init_common_variables(const char *conf_file_name, int argc,
sys_init_connect.value_length= 0;
if ((sys_init_connect.value= opt_init_connect))
sys_init_connect.value_length= strlen(opt_init_connect);
+ else
+ sys_init_connect.value=my_strdup("",MYF(0));
sys_init_slave.value_length= 0;
if ((sys_init_slave.value= opt_init_slave))
sys_init_slave.value_length= strlen(opt_init_slave);
+ else
+ sys_init_slave.value=my_strdup("",MYF(0));
if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
return 1;
@@ -2259,8 +2276,9 @@ static void init_ssl()
static int init_server_components()
{
DBUG_ENTER("init_server_components");
- table_cache_init();
- hostname_cache_init();
+ if (table_cache_init() || hostname_cache_init())
+ unireg_abort(1);
+
query_cache_result_size_limit(query_cache_limit);
query_cache_set_min_res_unit(query_cache_min_res_unit);
query_cache_resize(query_cache_size);
@@ -2341,7 +2359,8 @@ Now disabling --log-slave-updates.");
{
if (mlockall(MCL_CURRENT))
{
- sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno);
+ if (global_system_variables.log_warnings)
+ sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno);
}
else
locked_in_memory=1;
@@ -2362,7 +2381,7 @@ static void create_maintenance_thread()
{
if (
#ifdef HAVE_BERKELEY_DB
- !berkeley_skip ||
+ (have_berkeley_db == SHOW_OPTION_YES) ||
#endif
(flush_time && flush_time != ~(ulong) 0L))
{
@@ -2515,11 +2534,27 @@ int main(int argc, char **argv)
insensitive names. If this is not done the users MyISAM tables will
get corrupted if accesses with names of different case.
*/
+ DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
if (!lower_case_table_names &&
- test_if_case_insensitive(mysql_real_data_home) == 1)
+ (lower_case_file_system=
+ (test_if_case_insensitive(mysql_real_data_home) == 1)))
{
- sql_print_error("Warning: Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
- lower_case_table_names= 2;
+ if (lower_case_table_names_used)
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("\
+Warning: You have forced lower_case_table_names to 0 through a command-line \
+option, even though your file system '%s' is case insensitive. This means \
+that you can corrupt a MyISAM table by accessing it with different cases. \
+You should consider changing lower_case_table_names to 1 or 2",
+ mysql_real_data_home);
+ }
+ else
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("Warning: Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
+ lower_case_table_names= 2;
+ }
}
select_thread=pthread_self();
@@ -3628,7 +3663,7 @@ enum options_mysqld
OPT_OPEN_FILES_LIMIT,
OPT_PRELOAD_BUFFER_SIZE,
OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE,
- OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER,
+ OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, 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_DEBUGGING,
@@ -4209,11 +4244,11 @@ replicating a LOAD DATA INFILE command.",
NO_ARG, 0, 0, 0, 0, 0, 0},
{"log-warnings", 'W', "Log some not critical warnings to the log file.",
(gptr*) &global_system_variables.log_warnings,
- (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 1, 0, 0,
0, 0, 0},
{"warnings", 'W', "Deprecated ; Use --log-warnings instead.",
(gptr*) &global_system_variables.log_warnings,
- (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 1, 0, 0,
0, 0, 0},
{ "back_log", OPT_BACK_LOG,
"The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.",
@@ -4409,7 +4444,8 @@ The minimum value for this variable is 4096.",
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. If set to zero, which means INSERT DELAYED is not used.",
- (gptr*) &max_insert_delayed_threads, (gptr*) &max_insert_delayed_threads,
+ (gptr*) &global_system_variables.max_insert_delayed_threads,
+ (gptr*) &max_system_variables.max_insert_delayed_threads,
0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0},
{"max_error_count", OPT_MAX_ERROR_COUNT,
"Max number of errors/warnings to store for a statement.",
@@ -4546,12 +4582,17 @@ The minimum value for this variable is 4096.",
(gptr*) &global_system_variables.query_cache_type,
(gptr*) &max_system_variables.query_cache_type,
0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0},
+ {"query_cache_wlock_invalidate", OPT_QUERY_CACHE_WLOCK_INVALIDATE,
+ "Invalidate queries in query cache on LOCK for write",
+ (gptr*) &global_system_variables.query_cache_wlock_invalidate,
+ (gptr*) &max_system_variables.query_cache_wlock_invalidate,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
+#endif /*HAVE_QUERY_CACHE*/
{"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE,
"Persistent buffer for query parsing and execution",
(gptr*) &global_system_variables.query_prealloc_size,
(gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG,
REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
-#endif /*HAVE_QUERY_CACHE*/
{"read_buffer_size", OPT_RECORD_BUFFER,
"Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.",
(gptr*) &global_system_variables.read_buff_size,
@@ -4611,8 +4652,8 @@ The minimum value for this variable is 4096.",
1, 0},
{"table_cache", OPT_TABLE_CACHE,
"The number of open tables for all threads.", (gptr*) &table_cache_size,
- (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, ~0L, 0, 1,
- 0},
+ (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L,
+ 0, 1, 0},
{"thread_concurrency", OPT_THREAD_CONCURRENCY,
"Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.",
(gptr*) &concurrency, (gptr*) &concurrency, 0, GET_ULONG, REQUIRED_ARG,
@@ -5532,43 +5573,25 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case OPT_BDB:
#ifdef HAVE_BERKELEY_DB
if (opt_bdb)
- {
- berkeley_skip=0;
have_berkeley_db=SHOW_OPTION_YES;
- }
else
- {
- berkeley_skip=1;
have_berkeley_db=SHOW_OPTION_DISABLED;
- }
#endif
break;
case OPT_ISAM:
#ifdef HAVE_ISAM
if (opt_isam)
- {
- isam_skip=0;
have_isam= SHOW_OPTION_YES;
- }
else
- {
- isam_skip=1;
have_isam= SHOW_OPTION_DISABLED;
- }
#endif
break;
case OPT_INNODB:
#ifdef HAVE_INNOBASE_DB
if (opt_innodb)
- {
- innodb_skip=0;
have_innodb=SHOW_OPTION_YES;
- }
else
- {
- innodb_skip=1;
have_innodb=SHOW_OPTION_DISABLED;
- }
#endif
break;
case OPT_INNODB_DATA_FILE_PATH:
@@ -5632,6 +5655,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case OPT_LOWER_CASE_TABLE_NAMES:
lower_case_table_names= argument ? atoi(argument) : 1;
+ lower_case_table_names_used= 1;
break;
}
return 0;
@@ -5911,6 +5935,7 @@ static int test_if_case_insensitive(const char *dir_name)
File file;
char buff[FN_REFLEN], buff2[FN_REFLEN];
MY_STAT stat_info;
+ DBUG_ENTER("test_if_case_insensitive");
fn_format(buff, glob_hostname, dir_name, ".lower-test",
MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
@@ -5920,13 +5945,14 @@ static int test_if_case_insensitive(const char *dir_name)
if ((file= my_create(buff, 0666, O_RDWR, MYF(0))) < 0)
{
sql_print_error("Warning: Can't create test file %s", buff);
- return -1;
+ DBUG_RETURN(-1);
}
my_close(file, MYF(0));
if (my_stat(buff2, &stat_info, MYF(0)))
result= 1; // Can access file
(void) my_delete(buff, MYF(MY_WME));
- return result;
+ DBUG_PRINT("exit", ("result: %d", result));
+ DBUG_RETURN(result);
}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 6f97a5afe94..b6ac0eab53b 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1095,7 +1095,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
field->cmp_type() != value->result_type())
DBUG_RETURN(0);
- if (value->save_in_field(field, 1) > 0)
+ if (value->save_in_field(field, 1) < 0)
{
/* This happens when we try to insert a NULL field in a not null column */
DBUG_RETURN(&null_element); // cmp with NULL is never true
@@ -2154,6 +2154,7 @@ static ulong count_key_part_usage(SEL_ARG *root, SEL_ARG *key)
void SEL_ARG::test_use_count(SEL_ARG *root)
{
+ uint e_count=0;
if (this == root && use_count != 1)
{
sql_print_error("Note: Use_count: Wrong count %lu for root",use_count);
@@ -2161,7 +2162,6 @@ void SEL_ARG::test_use_count(SEL_ARG *root)
}
if (this->type != SEL_ARG::KEY_RANGE)
return;
- uint e_count=0;
for (SEL_ARG *pos=first(); pos ; pos=pos->next)
{
e_count++;
@@ -2178,8 +2178,8 @@ void SEL_ARG::test_use_count(SEL_ARG *root)
}
}
if (e_count != elements)
- sql_print_error("Warning: Wrong use count: %u for tree at %lx", e_count,
- (gptr) this);
+ sql_print_error("Warning: Wrong use count: %u (should be %u) for tree at %lx",
+ e_count, elements, (gptr) this);
}
#endif
@@ -2445,9 +2445,9 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
}
/* Get range for retrieving rows in QUICK_SELECT::get_next */
- if (!(range= new QUICK_RANGE(param->min_key,
+ if (!(range= new QUICK_RANGE((const char *) param->min_key,
(uint) (tmp_min_key - param->min_key),
- param->max_key,
+ (const char *) param->max_key,
(uint) (tmp_max_key - param->max_key),
flag)))
return 1; // out of memory
@@ -2560,8 +2560,8 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
QUICK_RANGE *null_range;
*ref->null_ref_key= 1; // Set null byte then create a range
- if (!(null_range= new QUICK_RANGE(ref->key_buff, ref->key_length,
- ref->key_buff, ref->key_length,
+ if (!(null_range= new QUICK_RANGE((char*)ref->key_buff, ref->key_length,
+ (char*)ref->key_buff, ref->key_length,
EQ_RANGE)))
goto err;
*ref->null_ref_key= 0; // Clear null byte
diff --git a/sql/protocol.h b/sql/protocol.h
index 67ae4ed01b4..17c8f0d321d 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -178,8 +178,3 @@ char *net_store_data(char *to,const char *from, uint length);
char *net_store_data(char *to,int32 from);
char *net_store_data(char *to,longlong from);
-#ifdef EMBEDDED_LIBRARY
-bool setup_params_data(struct st_prep_stmt *stmt);
-bool setup_params_data_withlog(struct st_prep_stmt *stmt);
-#endif
-
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index d125c95e839..284444090bb 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -768,7 +768,7 @@ int load_master_data(THD* thd)
We do not want anyone messing with the slave at all for the entire
duration of the data load.
*/
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
lock_slave_threads(active_mi);
init_thread_mask(&restart_thread_mask,active_mi,0 /*not inverse*/);
if (restart_thread_mask &&
@@ -777,7 +777,7 @@ int load_master_data(THD* thd)
{
send_error(thd,error);
unlock_slave_threads(active_mi);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
return 1;
}
@@ -895,7 +895,7 @@ int load_master_data(THD* thd)
cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
- // adjust position in the master
+ // adjust replication coordinates from the master
if (master_status_res)
{
MYSQL_ROW row = mysql_fetch_row(master_status_res);
@@ -908,10 +908,19 @@ int load_master_data(THD* thd)
*/
if (row && row[0] && row[1])
{
+ /*
+ If the slave's master info is not inited, we init it, then we write
+ the new coordinates to it. Must call init_master_info() *before*
+ setting active_mi, because init_master_info() sets active_mi with
+ defaults.
+ */
+ if (init_master_info(active_mi, master_info_file, relay_log_info_file,
+ 0))
+ send_error(thd, ER_MASTER_INFO);
strmake(active_mi->master_log_name, row[0],
sizeof(active_mi->master_log_name));
active_mi->master_log_pos = strtoull(row[1], (char**) 0, 10);
- // don't hit the magic number
+ /* at least in recent versions, the condition below should be false */
if (active_mi->master_log_pos < BIN_LOG_HEADER_SIZE)
active_mi->master_log_pos = BIN_LOG_HEADER_SIZE;
/*
@@ -938,7 +947,7 @@ int load_master_data(THD* thd)
{
send_error(thd, 0, "Failed purging old relay logs");
unlock_slave_threads(active_mi);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
return 1;
}
pthread_mutex_lock(&active_mi->rli.data_lock);
@@ -969,7 +978,7 @@ int load_master_data(THD* thd)
err:
unlock_slave_threads(active_mi);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
thd->proc_info = 0;
mysql_close(&mysql); // safe to call since we always do mysql_init()
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 12be0225421..8fe15b700f9 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -121,7 +121,8 @@ sys_var_character_set_server sys_character_set_server("character_set_server");
sys_var_str sys_charset_system("character_set_system",
sys_check_charset,
sys_update_charset,
- sys_set_default_charset);
+ sys_set_default_charset,
+ (char *)my_charset_utf8_general_ci.name);
sys_var_character_set_database sys_character_set_database("character_set_database");
sys_var_character_set_client sys_character_set_client("character_set_client");
sys_var_character_set_connection sys_character_set_connection("character_set_connection");
@@ -150,13 +151,14 @@ sys_var_long_ptr sys_flush_time("flush_time", &flush_time);
sys_var_str sys_ft_boolean_syntax("ft_boolean_syntax",
sys_check_ftb_syntax,
sys_update_ftb_syntax,
- sys_default_ftb_syntax);
+ sys_default_ftb_syntax,
+ ft_boolean_syntax);
sys_var_str sys_init_connect("init_connect", 0,
sys_update_init_connect,
- sys_default_init_connect);
+ sys_default_init_connect,0);
sys_var_str sys_init_slave("init_slave", 0,
sys_update_init_slave,
- sys_default_init_slave);
+ sys_default_init_slave,0);
sys_var_thd_ulong sys_interactive_timeout("interactive_timeout",
&SV::net_interactive_timeout);
sys_var_thd_ulong sys_join_buffer_size("join_buffer_size",
@@ -196,8 +198,10 @@ sys_var_long_ptr sys_max_connections("max_connections",
fix_max_connections);
sys_var_long_ptr sys_max_connect_errors("max_connect_errors",
&max_connect_errors);
-sys_var_long_ptr sys_max_delayed_threads("max_delayed_threads",
- &max_insert_delayed_threads,
+sys_var_thd_ulong sys_max_insert_delayed_threads("max_insert_delayed_threads",
+ &SV::max_insert_delayed_threads);
+sys_var_thd_ulong sys_max_delayed_threads("max_delayed_threads",
+ &SV::max_insert_delayed_threads,
fix_max_connections);
sys_var_thd_ulong sys_max_error_count("max_error_count",
&SV::max_error_count);
@@ -290,6 +294,9 @@ sys_var_long_ptr sys_query_cache_min_res_unit("query_cache_min_res_unit",
sys_var_thd_enum sys_query_cache_type("query_cache_type",
&SV::query_cache_type,
&query_cache_type_typelib);
+sys_var_thd_bool
+sys_query_cache_wlock_invalidate("query_cache_wlock_invalidate",
+ &SV::query_cache_wlock_invalidate);
#endif /* HAVE_QUERY_CACHE */
sys_var_bool_ptr sys_secure_auth("secure_auth", &opt_secure_auth);
sys_var_long_ptr sys_server_id("server_id",&server_id);
@@ -419,6 +426,16 @@ static sys_var_thd_ulong sys_default_week_format("default_week_format",
sys_var_thd_ulong sys_group_concat_max_len("group_concat_max_len",
&SV::group_concat_max_len);
+
+/* Read only variables */
+
+sys_var_const_str sys_os("version_compile_os", SYSTEM_TYPE);
+/* Global read-only variable describing server license */
+sys_var_const_str sys_license("license", LICENSE);
+
+
+
+
/*
List of all variables for initialisation and storage in hash
This is sorted in alphabetical order to make it easy to add new variables
@@ -471,6 +488,7 @@ sys_var *sys_variables[]=
&sys_key_cache_division_limit,
&sys_key_cache_age_threshold,
&sys_last_insert_id,
+ &sys_license,
&sys_local_infile,
&sys_log_binlog,
&sys_log_off,
@@ -485,6 +503,7 @@ sys_var *sys_variables[]=
&sys_max_connections,
&sys_max_delayed_threads,
&sys_max_error_count,
+ &sys_max_insert_delayed_threads,
&sys_max_heap_table_size,
&sys_max_join_size,
&sys_max_length_for_sort_data,
@@ -514,6 +533,7 @@ sys_var *sys_variables[]=
&sys_query_cache_limit,
&sys_query_cache_min_res_unit,
&sys_query_cache_type,
+ &sys_query_cache_wlock_invalidate,
#endif /* HAVE_QUERY_CACHE */
&sys_quote_show_create,
&sys_rand_seed1,
@@ -552,6 +572,7 @@ sys_var *sys_variables[]=
&sys_trans_alloc_block_size,
&sys_trans_prealloc_size,
&sys_tx_isolation,
+ &sys_os,
#ifdef HAVE_INNOBASE_DB
&sys_innodb_max_dirty_pages_pct,
#endif
@@ -569,22 +590,22 @@ struct show_var_st init_vars[]= {
{"basedir", mysql_home, SHOW_CHAR},
#ifdef HAVE_BERKELEY_DB
{"bdb_cache_size", (char*) &berkeley_cache_size, SHOW_LONG},
- {"bdb_log_buffer_size", (char*) &berkeley_log_buffer_size, SHOW_LONG},
{"bdb_home", (char*) &berkeley_home, SHOW_CHAR_PTR},
- {"bdb_max_lock", (char*) &berkeley_max_lock, SHOW_LONG},
{"bdb_logdir", (char*) &berkeley_logdir, SHOW_CHAR_PTR},
+ {"bdb_log_buffer_size", (char*) &berkeley_log_buffer_size, SHOW_LONG},
+ {"bdb_max_lock", (char*) &berkeley_max_lock, SHOW_LONG},
{"bdb_shared_data", (char*) &berkeley_shared_data, SHOW_BOOL},
{"bdb_tmpdir", (char*) &berkeley_tmpdir, SHOW_CHAR_PTR},
#endif
{sys_binlog_cache_size.name,(char*) &sys_binlog_cache_size, SHOW_SYS},
{sys_bulk_insert_buff_size.name,(char*) &sys_bulk_insert_buff_size,SHOW_SYS},
- {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS},
- {sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS},
- {sys_character_set_database.name, (char*) &sys_character_set_database,SHOW_SYS},
+ {"character_sets_dir", mysql_charsets_dir, SHOW_CHAR},
{sys_character_set_client.name,(char*) &sys_character_set_client, SHOW_SYS},
{sys_character_set_connection.name,(char*) &sys_character_set_connection,SHOW_SYS},
- {"character-sets-dir", mysql_charsets_dir, SHOW_CHAR},
+ {sys_character_set_database.name, (char*) &sys_character_set_database,SHOW_SYS},
{sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS},
+ {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS},
+ {sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS},
{sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS},
{sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS},
{sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS},
@@ -602,36 +623,34 @@ struct show_var_st init_vars[]= {
{sys_flush.name, (char*) &sys_flush, SHOW_SYS},
{sys_flush_time.name, (char*) &sys_flush_time, SHOW_SYS},
{sys_ft_boolean_syntax.name,(char*) &ft_boolean_syntax, SHOW_CHAR},
- {"ft_min_word_len", (char*) &ft_min_word_len, SHOW_LONG},
{"ft_max_word_len", (char*) &ft_max_word_len, SHOW_LONG},
+ {"ft_min_word_len", (char*) &ft_min_word_len, SHOW_LONG},
{"ft_query_expansion_limit",(char*) &ft_query_expansion_limit, SHOW_LONG},
{"ft_stopword_file", (char*) &ft_stopword_file, SHOW_CHAR_PTR},
{"have_bdb", (char*) &have_berkeley_db, SHOW_HAVE},
- {"have_crypt", (char*) &have_crypt, SHOW_HAVE},
{"have_compress", (char*) &have_compress, SHOW_HAVE},
+ {"have_crypt", (char*) &have_crypt, SHOW_HAVE},
{"have_innodb", (char*) &have_innodb, SHOW_HAVE},
{"have_isam", (char*) &have_isam, SHOW_HAVE},
- {"have_raid", (char*) &have_raid, SHOW_HAVE},
- {"have_symlink", (char*) &have_symlink, SHOW_HAVE},
{"have_openssl", (char*) &have_openssl, SHOW_HAVE},
{"have_query_cache", (char*) &have_query_cache, SHOW_HAVE},
- {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR},
+ {"have_raid", (char*) &have_raid, SHOW_HAVE},
+ {"have_symlink", (char*) &have_symlink, SHOW_HAVE},
{"init_connect", (char*) &sys_init_connect, SHOW_SYS},
+ {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR},
{"init_slave", (char*) &sys_init_slave, SHOW_SYS},
#ifdef HAVE_INNOBASE_DB
{"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
- {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG },
{"innodb_buffer_pool_awe_mem_mb", (char*) &innobase_buffer_pool_awe_mem_mb, SHOW_LONG },
+ {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG },
{"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR},
{"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR},
- {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG },
- {"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG },
- {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
- {"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG },
- {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT},
{"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL},
+ {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG },
{"innodb_file_per_table", (char*) &innobase_file_per_table, SHOW_MY_BOOL},
+ {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT},
{"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR},
+ {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
{"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG },
{"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR},
{"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL},
@@ -639,60 +658,67 @@ struct show_var_st init_vars[]= {
{"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONG},
{"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},
+ {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
+ {"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG },
+ {"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG },
#endif
{sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS},
{sys_join_buffer_size.name, (char*) &sys_join_buffer_size, SHOW_SYS},
{sys_key_buffer_size.name, (char*) &sys_key_buffer_size, SHOW_SYS},
+ {sys_key_cache_age_threshold.name, (char*) &sys_key_cache_age_threshold,
+ SHOW_SYS},
{sys_key_cache_block_size.name, (char*) &sys_key_cache_block_size,
- SHOW_SYS},
+ SHOW_SYS},
{sys_key_cache_division_limit.name, (char*) &sys_key_cache_division_limit,
- SHOW_SYS},
- {sys_key_cache_age_threshold.name, (char*) &sys_key_cache_age_threshold,
- SHOW_SYS},
+ SHOW_SYS},
{"language", language, SHOW_CHAR},
- {"large_files_support", (char*) &opt_large_files, SHOW_BOOL},
+ {"large_files_support", (char*) &opt_large_files, SHOW_BOOL},
+ {sys_license.name, (char*) &sys_license, SHOW_SYS},
{sys_local_infile.name, (char*) &sys_local_infile, SHOW_SYS},
#ifdef HAVE_MLOCKALL
{"locked_in_memory", (char*) &locked_in_memory, SHOW_BOOL},
#endif
{"log", (char*) &opt_log, SHOW_BOOL},
- {"log_update", (char*) &opt_update_log, SHOW_BOOL},
{"log_bin", (char*) &opt_bin_log, SHOW_BOOL},
+ {"log_error", (char*) log_error_file, SHOW_CHAR},
#ifdef HAVE_REPLICATION
{"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL},
#endif
{"log_slow_queries", (char*) &opt_slow_log, SHOW_BOOL},
+ {"log_update", (char*) &opt_update_log, SHOW_BOOL},
{sys_log_warnings.name, (char*) &sys_log_warnings, SHOW_SYS},
{sys_long_query_time.name, (char*) &sys_long_query_time, SHOW_SYS},
{sys_low_priority_updates.name, (char*) &sys_low_priority_updates, SHOW_SYS},
+ {"lower_case_file_system", (char*) &lower_case_file_system, SHOW_BOOL},
{"lower_case_table_names", (char*) &lower_case_table_names, SHOW_INT},
{sys_max_allowed_packet.name,(char*) &sys_max_allowed_packet, SHOW_SYS},
{sys_max_binlog_cache_size.name,(char*) &sys_max_binlog_cache_size, SHOW_SYS},
{sys_max_binlog_size.name, (char*) &sys_max_binlog_size, SHOW_SYS},
- {sys_max_connections.name, (char*) &sys_max_connections, SHOW_SYS},
{sys_max_connect_errors.name, (char*) &sys_max_connect_errors, SHOW_SYS},
- {sys_max_error_count.name, (char*) &sys_max_error_count, SHOW_SYS},
+ {sys_max_connections.name, (char*) &sys_max_connections, SHOW_SYS},
{sys_max_delayed_threads.name,(char*) &sys_max_delayed_threads, SHOW_SYS},
+ {sys_max_insert_delayed_threads.name,
+ (char*) &sys_max_insert_delayed_threads, SHOW_SYS},
+ {sys_max_error_count.name, (char*) &sys_max_error_count, SHOW_SYS},
{sys_max_heap_table_size.name,(char*) &sys_max_heap_table_size, SHOW_SYS},
{sys_max_join_size.name, (char*) &sys_max_join_size, SHOW_SYS},
- {sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS},
- {sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, SHOW_SYS},
{sys_max_length_for_sort_data.name, (char*) &sys_max_length_for_sort_data,
SHOW_SYS},
+ {sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS},
+ {sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, 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_user_connections.name,(char*) &sys_max_user_connections, 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,
SHOW_SYS},
+ {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
{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},
#ifdef __NT__
{"named_pipe", (char*) &opt_enable_named_pipe, SHOW_MY_BOOL},
@@ -705,10 +731,9 @@ struct show_var_st init_vars[]= {
{sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS},
{"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
- {"log_error", (char*) log_error_file, SHOW_CHAR},
{"port", (char*) &mysqld_port, SHOW_INT},
- {"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
+ {"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
SHOW_SYS},
#ifdef HAVE_QUERY_CACHE
@@ -717,7 +742,6 @@ struct show_var_st init_vars[]= {
SHOW_SYS},
{sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS},
{sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS},
- {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS},
#endif /* HAVE_QUERY_CACHE */
{sys_query_prealloc_size.name, (char*) &sys_query_prealloc_size, SHOW_SYS},
{sys_range_alloc_block_size.name, (char*) &sys_range_alloc_block_size,
@@ -729,18 +753,18 @@ struct show_var_st init_vars[]= {
{sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS},
#endif
{sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS},
+ {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS},
#ifdef HAVE_SMEM
{"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL},
{"shared_memory_base_name", (char*) &shared_memory_base_name, SHOW_CHAR_PTR},
#endif
{sys_server_id.name, (char*) &sys_server_id, SHOW_SYS},
-#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},
+#ifdef HAVE_REPLICATION
+ {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
+#endif
{sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS},
#ifdef HAVE_SYS_UN_H
{"socket", (char*) &mysqld_unix_port, SHOW_CHAR_PTR},
@@ -755,7 +779,6 @@ struct show_var_st init_vars[]= {
{"thread_concurrency", (char*) &concurrency, SHOW_LONG},
#endif
{"thread_stack", (char*) &thread_stack, SHOW_LONG},
- {sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS},
{sys_time_format.name, (char*) &sys_time_format, SHOW_SYS},
#ifdef HAVE_TZNAME
{"timezone", time_zone, SHOW_CHAR},
@@ -765,13 +788,14 @@ struct show_var_st init_vars[]= {
{sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size,
SHOW_SYS},
{sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS},
+ {sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS},
{"version", server_version, SHOW_CHAR},
#ifdef HAVE_BERKELEY_DB
{"version_bdb", (char*) DB_VERSION_STRING, SHOW_CHAR},
#endif
{"version_comment", (char*) MYSQL_COMPILATION_COMMENT, SHOW_CHAR},
{"version_compile_machine", (char*) MACHINE_TYPE, SHOW_CHAR},
- {"version_compile_os", (char*) SYSTEM_TYPE, SHOW_CHAR},
+ {sys_os.name, (char*) &sys_os, SHOW_SYS},
{sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS},
{NullS, NullS, SHOW_LONG}
};
@@ -811,15 +835,11 @@ bool sys_var_str::check(THD *thd, set_var *var)
bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
set_var *var)
{
- char *res= 0, *old_value;
- uint new_length= 0;
- /* If the string is "", delete old init command */
- if (var && (new_length= var->value->str_value.length()))
- {
- if (!(res= my_strdup_with_length((byte*) var->value->str_value.ptr(),
- new_length, MYF(0))))
- return 1;
- }
+ char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
+ uint new_length= (var ? var->value->str_value.length() : 0);
+ if (!old_value) old_value="";
+ if (!(res= my_strdup_with_length(old_value, new_length, MYF(0))))
+ return 1;
/*
Replace the old value in such a way that the any thread using
the value will work.
@@ -1063,7 +1083,8 @@ static void fix_max_relay_log_size(THD *thd, enum_var_type type)
static void fix_max_connections(THD *thd, enum_var_type type)
{
- resize_thr_alarm(max_connections + max_insert_delayed_threads + 10);
+ resize_thr_alarm(max_connections +
+ global_system_variables.max_insert_delayed_threads + 10);
}
@@ -1401,7 +1422,7 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
if (var_type != OPT_DEFAULT)
{
net_printf(thd, ER_INCORRECT_GLOBAL_LOCAL_VAR,
- name, var_type == OPT_GLOBAL ? "LOCAL" : "GLOBAL");
+ name, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
return 0;
}
/* As there was no local variable, return the global value */
@@ -2167,7 +2188,7 @@ bool sys_var_pseudo_thread_id::check(THD *thd, set_var *var)
bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
{
int result= 0;
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
pthread_mutex_lock(&active_mi->rli.run_lock);
if (active_mi->rli.slave_running)
{
@@ -2175,7 +2196,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
result=1;
}
pthread_mutex_unlock(&active_mi->rli.run_lock);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
var->save_result.ulong_value= (ulong) var->value->val_int();
return result;
}
@@ -2183,7 +2204,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
{
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
pthread_mutex_lock(&active_mi->rli.run_lock);
/*
The following test should normally never be true as we test this
@@ -2197,7 +2218,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
pthread_mutex_unlock(&active_mi->rli.data_lock);
}
pthread_mutex_unlock(&active_mi->rli.run_lock);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
return 0;
}
#endif /* HAVE_REPLICATION */
@@ -2501,7 +2522,7 @@ int set_var_user::check(THD *thd)
{
/*
Item_func_set_user_var can't substitute something else on its place =>
- 0 can be passed as last argument
+ 0 can be passed as last argument (reference on item)
*/
return (user_var_item->fix_fields(thd, 0, (Item**) 0) ||
user_var_item->check()) ? -1 : 0;
diff --git a/sql/set_var.h b/sql/set_var.h
index 9087a3e023e..dc5b1bf927f 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -139,8 +139,9 @@ public:
sys_var_str(const char *name_arg,
sys_check_func check_func_arg,
sys_update_func update_func_arg,
- sys_set_default_func set_default_func_arg)
- :sys_var(name_arg), check_func(check_func_arg),
+ sys_set_default_func set_default_func_arg,
+ char *value_arg)
+ :sys_var(name_arg), value(value_arg), check_func(check_func_arg),
update_func(update_func_arg),set_default_func(set_default_func_arg)
{}
bool check(THD *thd, set_var *var);
@@ -163,6 +164,34 @@ public:
};
+class sys_var_const_str :public sys_var
+{
+public:
+ char *value; // Pointer to const value
+ sys_var_const_str(const char *name_arg, const char *value_arg)
+ :sys_var(name_arg), value((char*) value_arg)
+ {}
+ bool check(THD *thd, set_var *var)
+ {
+ return 1;
+ }
+ bool update(THD *thd, set_var *var)
+ {
+ return 1;
+ }
+ SHOW_TYPE type() { return SHOW_CHAR; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ {
+ return (byte*) value;
+ }
+ bool check_update_type(Item_result type)
+ {
+ return 1;
+ }
+ bool check_default(enum_var_type type) { return 1; }
+};
+
+
class sys_var_enum :public sys_var
{
uint *value;
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 95ca1c7caa0..21dd24c540b 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -240,7 +240,7 @@ character-set=latin2
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -287,7 +287,7 @@ character-set=latin2
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -301,5 +301,7 @@ character-set=latin2
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updatable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 31be0288aa4..94a2091ed1d 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -234,7 +234,7 @@ character-set=latin1
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -281,7 +281,7 @@ character-set=latin1
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support, they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -295,5 +295,7 @@ character-set=latin1
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index e334beb13c8..967f5c0ece0 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -242,7 +242,7 @@ character-set=latin1
"Optie '%s' tweemaal gebruikt in opdracht",
"Gebruiker '%-.64s' heeft het maximale gebruik van de '%s' faciliteit overschreden (huidige waarde: %ld)",
"Toegang geweigerd. U moet het %-.128s privilege hebben voor deze operatie",
-"Variabele '%-.64s' is LOCAL en kan niet worden gebruikt met SET GLOBAL",
+"Variabele '%-.64s' is SESSION en kan niet worden gebruikt met SET GLOBAL",
"Variabele '%-.64s' is GLOBAL en dient te worden gewijzigd met SET GLOBAL",
"Variabele '%-.64s' heeft geen standaard waarde",
"Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.64s'",
@@ -289,7 +289,7 @@ character-set=latin1
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -303,5 +303,7 @@ character-set=latin1
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 8b3ee786aa1..fd2e97754b5 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -231,7 +231,7 @@ character-set=latin1
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -278,7 +278,7 @@ character-set=latin1
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL. Otherwise you will get problems if you get an unexpected slave's mysqld restart",
@@ -292,5 +292,7 @@ character-set=latin1
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updatable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 9a76d832996..350dff5e4f8 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -236,7 +236,7 @@ character-set=latin7
"Määrangut '%s' on lauses kasutatud topelt",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -283,7 +283,7 @@ character-set=latin7
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -297,5 +297,7 @@ character-set=latin7
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 1c793faa7e4..cba2b2e4264 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -231,7 +231,7 @@ character-set=latin1
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -278,7 +278,7 @@ character-set=latin1
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -292,5 +292,7 @@ character-set=latin1
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 8290cc60933..cc107f80f93 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -290,7 +290,7 @@ character-set=latin1
"Variable '%-.64s' ist keine Variablen-Komponenten (kann nicht als XXXX.variablen_name verwendet werden)",
"Unbekannte Kollation: '%-.64s'",
"SSL-Parameter in CHANGE MASTER werden ignoriert, weil dieser MySQL-Slave ohne SSL-Unterstützung kompiliert wurde. Sie können aber später verwendet werden, wenn der MySQL-Slave mit SSL gestartet wird",
-"Server läuft im Modus --secure-auth, aber '%s@%s' hat ein Passwort im alten Format. Bitte Passwort ins neue Format ändern",
+"Server läuft im Modus --secure-auth, aber '%s'@'%s' hat ein Passwort im alten Format. Bitte Passwort ins neue Format ändern",
"Feld oder Verweis '%-.64s%s%-.64s%s%-.64s' im SELECT-Befehl Nr. %d wurde im SELECT-Befehl Nr. %d aufgelöst",
"Falscher Parameter oder falsche Kombination von Parametern für START SLAVE UNTIL",
"Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn der Slave-Server unerwartet neu startet",
@@ -304,5 +304,7 @@ character-set=latin1
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 95c545a220a..b6a2e9a699c 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -231,7 +231,7 @@ character-set=greek
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -278,7 +278,7 @@ character-set=greek
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -292,5 +292,7 @@ character-set=greek
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 6c8e0bc88af..80c840af081 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -233,7 +233,7 @@ character-set=latin2
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -280,7 +280,7 @@ character-set=latin2
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -294,5 +294,7 @@ character-set=latin2
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 1ac30af2e29..e499d1b663c 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -231,7 +231,7 @@ character-set=latin1
"L'opzione '%s' e' stata usata due volte nel comando",
"L'utente '%-.64s' ha ecceduto la risorsa '%s' (valore corrente: %ld)",
"Accesso non consentito. Serve il privilegio %-.128s per questa operazione",
-"La variabile '%-.64s' e' una variabile locale ( LOCAL ) e non puo' essere cambiata usando SET GLOBAL",
+"La variabile '%-.64s' e' una variabile locale ( SESSION ) e non puo' essere cambiata usando SET GLOBAL",
"La variabile '%-.64s' e' una variabile globale ( GLOBAL ) e deve essere cambiata usando SET GLOBAL",
"La variabile '%-.64s' non ha un valore di default",
"Alla variabile '%-.64s' non puo' essere assegato il valore '%-.64s'",
@@ -278,7 +278,7 @@ character-set=latin1
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -292,5 +292,7 @@ character-set=latin1
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index b83dd86e433..75ee30abad9 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -233,7 +233,7 @@ character-set=ujis
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -280,7 +280,7 @@ character-set=ujis
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -294,5 +294,7 @@ character-set=ujis
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index fed4a749e6a..43b34cc65dc 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -231,7 +231,7 @@ character-set=euckr
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -278,7 +278,7 @@ character-set=euckr
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -292,5 +292,7 @@ character-set=euckr
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 3356ab05406..49b6577c16a 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -233,7 +233,7 @@ character-set=latin1
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -280,7 +280,7 @@ character-set=latin1
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -294,5 +294,7 @@ character-set=latin1
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 1d1146bea22..bdfcd2dd819 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -233,7 +233,7 @@ character-set=latin1
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -280,7 +280,7 @@ character-set=latin1
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -294,5 +294,7 @@ character-set=latin1
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index b1a170f68aa..8bb089b03c9 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -235,7 +235,7 @@ character-set=latin2
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -282,7 +282,7 @@ character-set=latin2
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -296,5 +296,7 @@ character-set=latin2
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 800a2015094..3ccbb48eede 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -232,7 +232,7 @@ character-set=latin1
"Opção '%s' usada duas vezes no comando",
"Usuário '%-.64s' tem excedido o '%s' recurso (atual valor: %ld)",
"Acesso negado. Você precisa o privilégio %-.128s para essa operação",
-"Variável '%-.64s' é uma LOCAL variável e não pode ser usada com SET GLOBAL",
+"Variável '%-.64s' é uma SESSION variável e não pode ser usada com SET GLOBAL",
"Variável '%-.64s' é uma GLOBAL variável e deve ser configurada com SET GLOBAL",
"Variável '%-.64s' não tem um valor padrão",
"Variável '%-.64s' não pode ser configurada para o valor de '%-.64s'",
@@ -279,7 +279,7 @@ character-set=latin1
"Variável '%-.64s' não é uma variável componente (Não pode ser usada como XXXX.variável_nome)",
"Collation desconhecida: '%-.64s'",
"SSL parâmetros em CHANGE MASTER são ignorados porque este escravo MySQL foi compilado sem o SSL suporte. Os mesmos podem ser usados mais tarde quando o escravo MySQL com SSL seja iniciado.",
-"Servidor está rodando em --secure-auth modo, porêm '%s@%s' tem senha no formato antigo; por favor troque a senha para o novo formato",
+"Servidor está rodando em --secure-auth modo, porêm '%s'@'%s' tem senha no formato antigo; por favor troque a senha para o novo formato",
"Campo ou referência '%-.64s%s%-.64s%s%-.64s' de SELECT #%d foi resolvido em SELECT #%d",
"Parâmetro ou combinação de parâmetros errado para START SLAVE UNTIL",
"É recomendado para rodar com --skip-slave-start quando fazendo replicação passo-por-passo com START SLAVE UNTIL, de outra forma você não está seguro em caso de inesperada reinicialição do mysqld escravo",
@@ -293,5 +293,7 @@ character-set=latin1
"Motor de tabela desconhecido '%s'",
"'%s' é desatualizado. Use '%s' em seu lugar",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index f35df81d15e..92b347ebe7e 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -235,7 +235,7 @@ character-set=latin2
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -282,7 +282,7 @@ character-set=latin2
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -296,5 +296,7 @@ character-set=latin2
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 6404948449e..25d2c0bb049 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -233,7 +233,7 @@ character-set=koi8r
"ïÐÃÉÑ '%s' Ä×ÁÖÄÙ ÉÓÐÏÌØÚÏ×ÁÎÁ × ×ÙÒÁÖÅÎÉÉ",
"ðÏÌØÚÏ×ÁÔÅÌØ '%-.64s' ÐÒÅ×ÙÓÉÌ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÒÅÓÕÒÓÁ '%s' (ÔÅËÕÝÅÅ ÚÎÁÞÅÎÉÅ: %ld)",
"÷ ÄÏÓÔÕÐÅ ÏÔËÁÚÁÎÏ. ÷ÁÍ ÎÕÖÎÙ ÐÒÉ×ÉÌÅÇÉÉ %-.128s ÄÌÑ ÜÔÏÊ ÏÐÅÒÁÃÉÉ",
-"ðÅÒÅÍÅÎÎÁÑ '%-.64s' Ñ×ÌÑÅÔÓÑ ÐÏÔÏËÏ×ÏÊ (LOCAL) ÐÅÒÅÍÅÎÎÏÊ É ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÚÍÅÎÅÎÁ Ó ÐÏÍÏÝØÀ SET GLOBAL",
+"ðÅÒÅÍÅÎÎÁÑ '%-.64s' Ñ×ÌÑÅÔÓÑ ÐÏÔÏËÏ×ÏÊ (SESSION) ÐÅÒÅÍÅÎÎÏÊ É ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÚÍÅÎÅÎÁ Ó ÐÏÍÏÝØÀ SET GLOBAL",
"ðÅÒÅÍÅÎÎÁÑ '%-.64s' Ñ×ÌÑÅÔÓÑ ÇÌÏÂÁÌØÎÏÊ (GLOBAL) ÐÅÒÅÍÅÎÎÏÊ, É ÅÅ ÓÌÅÄÕÅÔ ÉÚÍÅÎÑÔØ Ó ÐÏÍÏÝØÀ SET GLOBAL",
"ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÎÅ ÉÍÅÅÔ ÚÎÁÞÅÎÉÑ ÐÏ ÕÍÏÌÞÁÎÉÀ",
"ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÕÓÔÁÎÏ×ÌÅÎÁ × ÚÎÁÞÅÎÉÅ '%-.64s'",
@@ -280,7 +280,7 @@ character-set=koi8r
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"óÅÒ×ÅÒ ÚÁÐÕÝÅÎ × ÒÅÖÉÍÅ --secure-auth (ÂÅÚÏÐÁÓÎÏÊ Á×ÔÏÒÉÚÁÃÉÉ), ÎÏ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%s@%s' ÐÁÒÏÌØ ÓÏÈÒÁÎ£Î × ÓÔÁÒÏÍ ÆÏÒÍÁÔÅ; ÎÅÏÂÈÏÄÉÍÏ ÏÂÎÏ×ÉÔØ ÆÏÒÍÁÔ ÐÁÒÏÌÑ",
+"óÅÒ×ÅÒ ÚÁÐÕÝÅÎ × ÒÅÖÉÍÅ --secure-auth (ÂÅÚÏÐÁÓÎÏÊ Á×ÔÏÒÉÚÁÃÉÉ), ÎÏ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%s'@'%s' ÐÁÒÏÌØ ÓÏÈÒÁÎ£Î × ÓÔÁÒÏÍ ÆÏÒÍÁÔÅ; ÎÅÏÂÈÏÄÉÍÏ ÏÂÎÏ×ÉÔØ ÆÏÒÍÁÔ ÐÁÒÏÌÑ",
"ðÏÌÅ ÉÌÉ ÓÓÙÌËÁ '%-.64s%s%-.64s%s%-.64s' ÉÚ SELECTÁ #%d ÂÙÌÁ ÎÁÊÄÅÎÁ × SELECTÅ #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -294,5 +294,7 @@ character-set=koi8r
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"ôÁÂÌÉÃÁ %-.100s × %s ÎÅ ÍÏÖÅÔ ÉÚÍÅÎÑÔÓÑ",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index c60cd06802d..3c94ec65060 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -272,7 +272,7 @@ character-set=cp1250
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -286,5 +286,7 @@ character-set=cp1250
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updatable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working"
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working"
"The MySQL server is running with the %s option so it cannot execute this statement"
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 2874c68f8aa..7889c1edaec 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -239,7 +239,7 @@ character-set=latin2
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -286,7 +286,7 @@ character-set=latin2
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -300,5 +300,7 @@ character-set=latin2
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 86da8db1fbe..db62b0e6cd4 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -233,7 +233,7 @@ character-set=latin1
"Opción '%s' usada dos veces en el comando",
"Usuario '%-.64s' ha excedido el recurso '%s' (actual valor: %ld)",
"Acceso negado. Usted necesita el privilegio %-.128s para esta operación",
-"Variable '%-.64s' es una LOCAL variable y no puede ser usada con SET GLOBAL",
+"Variable '%-.64s' es una SESSION variable y no puede ser usada con SET GLOBAL",
"Variable '%-.64s' es una GLOBAL variable y no puede ser configurada con SET GLOBAL",
"Variable '%-.64s' no tiene un valor patrón",
"Variable '%-.64s' no puede ser configurada para el valor de '%-.64s'",
@@ -280,7 +280,7 @@ character-set=latin1
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -294,5 +294,7 @@ character-set=latin1
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 7b9e593ec1e..4d069e01b1f 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -231,7 +231,7 @@ character-set=latin1
"Option '%s' användes två gånger",
"Användare '%-.64s' har överskridit '%s' (nuvarande värde: %ld)",
"Du har inte privlegiet '%-.128s' som behövs för denna operation",
-"Variabel '%-.64s' är en LOCAL variabel och kan inte ändrad med SET GLOBAL",
+"Variabel '%-.64s' är en SESSION variabel och kan inte ändrad med SET GLOBAL",
"Variabel '%-.64s' är en GLOBAL variabel och bör sättas med SET GLOBAL",
"Variabel '%-.64s' har inte ett DEFAULT-värde",
"Variabel '%-.64s' kan inte sättas till '%-.64s'",
@@ -278,7 +278,7 @@ character-set=latin1
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -294,3 +294,5 @@ character-set=latin1
"'%s' är inte aktiverad; För att aktivera detta måste du bygga om MySQL med '%s' definerad",
"MySQL är started i --skip-grant-tables mod. Pga av detta kan du inte använda detta program",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index a2f45f78d25..c2d5def0646 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -236,7 +236,7 @@ character-set=koi8u
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
@@ -283,7 +283,7 @@ character-set=koi8u
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
+"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"óÔÏ×ÂÅÃØ ÁÂÏ ÐÏÓÉÌÁÎÎÑ '%-.64s%s%-.64s%s%-.64s' ¦Ú SELECTÕ #%d ÂÕÌÏ ÚÎÁÊÄÅÎÅ Õ SELECT¦ #%d",
"Wrong parameter or combination of parameters for START SLAVE UNTIL",
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
@@ -297,5 +297,7 @@ character-set=koi8u
"Unknown table engine '%s'",
"'%s' is deprecated, use '%s' instead",
"ôÁÂÌÉÃÑ %-.100s Õ %s ÎÅ ÍÏÖÅ ÏÎÏ×ÌÀ×ÁÔÉÓØ",
-"The '%s' feature was disabled; you need MySQL built with '%s' define to have it working",
+"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
+"Column '%-.100s' has duplicated value '%-.64s' in %s"
+"Truncated wrong %-.32s value: '%-.128s'"
diff --git a/sql/slave.cc b/sql/slave.cc
index bbf1741183b..5493d422d37 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -35,7 +35,6 @@ typedef bool (*CHECK_KILLED_FUNC)(THD*,void*);
volatile bool slave_sql_running = 0, slave_io_running = 0;
char* slave_load_tmpdir = 0;
MASTER_INFO *active_mi;
-volatile int active_mi_in_use = 0;
HASH replicate_do_table, replicate_ignore_table;
DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
bool do_table_inited = 0, ignore_table_inited = 0;
@@ -138,8 +137,12 @@ int init_slave()
{
DBUG_ENTER("init_slave");
- /* This is called when mysqld starts */
-
+ /*
+ This is called when mysqld starts. Before client connections are
+ accepted. However bootstrap may conflict with us if it does START SLAVE.
+ So it's safer to take the lock.
+ */
+ pthread_mutex_lock(&LOCK_active_mi);
/*
TODO: re-write this to interate through the list of files
for multi-master
@@ -184,9 +187,11 @@ int init_slave()
goto err;
}
}
+ pthread_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(0);
err:
+ pthread_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(1);
}
@@ -863,7 +868,14 @@ static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
void end_slave()
{
- /* This is called when the server terminates, in close_connections(). */
+ /*
+ This is called when the server terminates, in close_connections().
+ It terminates slave threads. However, some CHANGE MASTER etc may still be
+ running presently. If a START SLAVE was in progress, the mutex lock below
+ will make us wait until slave threads have started, and START SLAVE
+ returns, then we terminate them here.
+ */
+ pthread_mutex_lock(&LOCK_active_mi);
if (active_mi)
{
/*
@@ -884,6 +896,7 @@ void end_slave()
delete active_mi;
active_mi= 0;
}
+ pthread_mutex_unlock(&LOCK_active_mi);
}
@@ -1821,9 +1834,9 @@ file '%s')", fname);
mi->master_log_name,
(ulong) mi->master_log_pos));
+ mi->rli.mi = mi;
if (init_relay_log_info(&mi->rli, slave_info_fname))
goto err;
- mi->rli.mi = mi;
mi->inited = 1;
// now change cache READ -> WRITE - must do this before flush_master_info
@@ -2060,10 +2073,29 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
protocol->store(mi->ssl_key, &my_charset_bin);
if (mi->rli.last_master_timestamp)
- protocol->store((ulonglong)
- (long)((time_t)time((time_t*) 0)
- - mi->rli.last_master_timestamp)
- - mi->clock_diff_with_master);
+ {
+ long tmp= (long)((time_t)time((time_t*) 0)
+ - mi->rli.last_master_timestamp)
+ - mi->clock_diff_with_master;
+ /*
+ Apparently on some systems tmp can be <0. Here are possible reasons
+ related to MySQL:
+ - the master is itself a slave of another master whose time is ahead.
+ - somebody used an explicit SET TIMESTAMP on the master.
+ Possible reason related to granularity-to-second of time functions
+ (nothing to do with MySQL), which can explain a value of -1:
+ assume the master's and slave's time are perfectly synchronized, and
+ that at slave's connection time, when the master's timestamp is read,
+ it is at the very end of second 1, and (a very short time later) when
+ the slave's timestamp is read it is at the very beginning of second
+ 2. Then the recorded value for master is 1 and the recorded value for
+ slave is 2. At SHOW SLAVE STATUS time, assume that the difference
+ between timestamp of slave and rli->last_master_timestamp is 0
+ (i.e. they are in the same second), then we get 0-(2-1)=-1 as a result.
+ This confuses users, so we don't go below 0.
+ */
+ protocol->store((longlong)(max(0, tmp)));
+ }
else
protocol->store_null();
@@ -2566,13 +2598,6 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error)
case ER_NET_ERROR_ON_WRITE:
case ER_SERVER_SHUTDOWN:
case ER_NEW_ABORTING_CONNECTION:
- slave_print_error(rli,expected_error,
- "query '%s' partially completed on the master \
-and was aborted. There is a chance that your master is inconsistent at this \
-point. If you are sure that your master is ok, run this query manually on the\
- slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;\
- SLAVE START; .", thd->query);
- thd->query_error= 1;
return 1;
default:
return 0;
@@ -3163,7 +3188,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
llstr(rli->group_relay_log_pos,llbuff1));
/* execute init_slave variable */
- if (sys_init_slave.value)
+ if (sys_init_slave.value_length)
{
execute_init_command(thd, &sys_init_slave, &LOCK_sys_init_slave);
if (thd->query_error)
@@ -3822,6 +3847,7 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli)
error=1;
if (flush_io_cache(file))
error=1;
+ /* Flushing the relay log is done by the slave I/O thread */
return error;
}
diff --git a/sql/slave.h b/sql/slave.h
index d92c44dd2ba..549ceb5d42c 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -35,12 +35,19 @@
/*
MUTEXES in replication:
- LOCK_active_mi: this is meant for multimaster, when we can switch from a
- master to another. It protects active_mi. We don't care of it for the moment,
- as active_mi never moves (it's created at startup and deleted at shutdown,
- and not changed: it always points to the same MASTER_INFO struct), because we
- don't have multimaster. So for the moment, mi does not move, and mi->rli does
- not either.
+ LOCK_active_mi: [note: this was originally meant for multimaster, to switch
+ from a master to another, to protect active_mi] It is used to SERIALIZE ALL
+ administrative commands of replication: START SLAVE, STOP SLAVE, CHANGE
+ MASTER, RESET SLAVE, end_slave() (when mysqld stops) [init_slave() does not
+ need it it's called early]. Any of these commands holds the mutex from the
+ start till the end. This thus protects us against a handful of deadlocks
+ (consider start_slave_thread() which, when starting the I/O thread, releases
+ mi->run_lock, keeps rli->run_lock, and tries to re-acquire mi->run_lock).
+
+ Currently active_mi never moves (it's created at startup and deleted at
+ shutdown, and not changed: it always points to the same MASTER_INFO struct),
+ because we don't have multimaster. So for the moment, mi does not move, and
+ mi->rli does not either.
In MASTER_INFO: run_lock, data_lock
run_lock protects all information about the run state: slave_running, and the
@@ -51,6 +58,9 @@
In RELAY_LOG_INFO: run_lock, data_lock
see MASTER_INFO
+ Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you
+ must acquire LOCK_active_mi first.
+
In MYSQL_LOG: LOCK_log, LOCK_index of the binlog and the relay log
LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog
(so that you have to update the .index file).
@@ -72,20 +82,7 @@ enum enum_binlog_formats {
BINLOG_FORMAT_323_LESS_57,
BINLOG_FORMAT_323_GEQ_57 };
-/*
- TODO: this needs to be redone, but for now it does not matter since
- we do not have multi-master yet.
-*/
-
-#define LOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
- ++active_mi_in_use; \
- pthread_mutex_unlock(&LOCK_active_mi);}
-
-#define UNLOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
- --active_mi_in_use; \
- pthread_mutex_unlock(&LOCK_active_mi); }
-
-/*****************************************************************************
+/****************************************************************************
Replication SQL Thread
@@ -206,12 +203,16 @@ typedef struct st_relay_log_info
bool ignore_log_space_limit;
/*
- InnoDB internally stores the master log position it has processed
- so far; the position to store is really the sum of
- pos + pending + event_len here since we must store the pos of the
- END of the current log event
+ When it commits, InnoDB internally stores the master log position it has
+ processed so far; the position to store is the one of the end of the
+ committing event (the COMMIT query event, or the event if in autocommit
+ mode).
*/
- int event_len;
+#if MYSQL_VERSION_ID < 40100
+ ulonglong future_master_log_pos;
+#else
+ ulonglong future_group_master_log_pos;
+#endif
time_t last_master_timestamp;
@@ -550,7 +551,6 @@ extern "C" pthread_handler_decl(handle_slave_io,arg);
extern "C" pthread_handler_decl(handle_slave_sql,arg);
extern bool volatile abort_loop;
extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
-extern volatile int active_mi_in_use;
extern LIST master_list;
extern HASH replicate_do_table, replicate_ignore_table;
extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
diff --git a/sql/spatial.cc b/sql/spatial.cc
index d19429fdd9c..ab415d9af10 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -1,145 +1,183 @@
-#include "mysql_priv.h"
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "mysql_priv.h"
#define MAX_DIGITS_IN_DOUBLE 16
-/***************************** GClassInfo *******************************/
-
-#define IMPLEMENT_GEOM(class_name, type_id, name) \
-{ \
- (GF_InitFromText) &class_name::init_from_wkt, \
- (GF_GetDataAsText) &class_name::get_data_as_wkt, \
- (GF_GetDataSize) &class_name::get_data_size, \
- (GF_GetMBR) &class_name::get_mbr, \
- (GF_GetD) &class_name::get_x, \
- (GF_GetD) &class_name::get_y, \
- (GF_GetD) &class_name::length, \
- (GF_GetD) &class_name::area, \
- (GF_GetI) &class_name::is_closed, \
- (GF_GetUI) &class_name::num_interior_ring, \
- (GF_GetUI) &class_name::num_points, \
- (GF_GetUI) &class_name::num_geometries, \
- (GF_GetUI) &class_name::dimension, \
- (GF_GetWS) &class_name::start_point, \
- (GF_GetWS) &class_name::end_point, \
- (GF_GetWS) &class_name::exterior_ring, \
- (GF_GetWS) &class_name::centroid, \
- (GF_GetUIWS) &class_name::point_n, \
- (GF_GetUIWS) &class_name::interior_ring_n, \
- (GF_GetUIWS) &class_name::geometry_n, \
- class_name::type_id, \
- name, \
- NULL \
-},
-
-
-static Geometry::GClassInfo ci_collection[] =
-{
- IMPLEMENT_GEOM(GPoint, wkbPoint, "POINT")
- IMPLEMENT_GEOM(GLineString, wkbLineString, "LINESTRING")
- IMPLEMENT_GEOM(GPolygon, wkbPolygon, "POLYGON")
- IMPLEMENT_GEOM(GMultiPoint, wkbMultiPoint, "MULTIPOINT")
- IMPLEMENT_GEOM(GMultiLineString, wkbMultiLineString, "MULTILINESTRING")
- IMPLEMENT_GEOM(GMultiPolygon, wkbMultiPolygon, "MULTIPOLYGON")
- IMPLEMENT_GEOM(GGeometryCollection, wkbGeometryCollection, "GEOMETRYCOLLECTION")
+/***************************** Gis_class_info *******************************/
+
+Geometry::Class_info *Geometry::ci_collection[Geometry::wkb_end+1]=
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-static Geometry::GClassInfo *ci_collection_end = ci_collection + sizeof(ci_collection)/sizeof(ci_collection[0]);
+static Geometry::Class_info **ci_collection_end=
+ Geometry::ci_collection+Geometry::wkb_end + 1;
-/***************************** Geometry *******************************/
+Geometry::Class_info::Class_info(const char *name, int type_id,
+ void(*create_func)(void *)):
+ m_name(name, strlen(name)), m_type_id(type_id), m_create_func(create_func)
+{
+ ci_collection[type_id]= this;
+}
-Geometry::GClassInfo *Geometry::find_class(int type_id)
+static void create_point(void *buffer)
{
- for (GClassInfo *cur_rt = ci_collection; cur_rt < ci_collection_end; ++cur_rt)
- {
- if (cur_rt->m_type_id == type_id)
- {
- return cur_rt;
- }
- }
- return NULL;
+ new(buffer) Gis_point;
}
-
-Geometry::GClassInfo *Geometry::find_class(const char *name, size_t len)
+
+static void create_linestring(void *buffer)
+{
+ new(buffer) Gis_line_string;
+}
+
+static void create_polygon(void *buffer)
{
- for (GClassInfo *cur_rt = ci_collection;
- cur_rt < ci_collection_end; ++cur_rt)
+ new(buffer) Gis_polygon;
+}
+
+static void create_multipoint(void *buffer)
+{
+ new(buffer) Gis_multi_point;
+}
+
+static void create_multipolygon(void *buffer)
+{
+ new(buffer) Gis_multi_polygon;
+}
+
+static void create_multilinestring(void *buffer)
+{
+ new(buffer) Gis_multi_line_string;
+}
+
+static void create_geometrycollection(void *buffer)
+{
+ new(buffer) Gis_geometry_collection;
+}
+
+
+
+static Geometry::Class_info point_class("POINT",
+ Geometry::wkb_point, create_point);
+
+static Geometry::Class_info linestring_class("LINESTRING",
+ Geometry::wkb_linestring,
+ create_linestring);
+static Geometry::Class_info polygon_class("POLYGON",
+ Geometry::wkb_polygon,
+ create_polygon);
+static Geometry::Class_info multipoint_class("MULTIPOINT",
+ Geometry::wkb_multipoint,
+ create_multipoint);
+static Geometry::Class_info
+multilinestring_class("MULTILINESTRING",
+ Geometry::wkb_multilinestring, create_multilinestring);
+static Geometry::Class_info multipolygon_class("MULTIPOLYGON",
+ Geometry::wkb_multipolygon,
+ create_multipolygon);
+static Geometry::Class_info
+geometrycollection_class("GEOMETRYCOLLECTION",Geometry::wkb_geometrycollection,
+ create_geometrycollection);
+
+/***************************** Geometry *******************************/
+
+Geometry::Class_info *Geometry::find_class(const char *name, uint32 len)
+{
+ for (Class_info **cur_rt= ci_collection;
+ cur_rt < ci_collection_end; cur_rt++)
{
- if ((cur_rt->m_name[len] == 0) &&
- (my_strnncoll(&my_charset_latin1, (const uchar*)cur_rt->m_name, len,
- (const uchar*)name, len) == 0))
- {
- return cur_rt;
- }
+ if (*cur_rt &&
+ ((*cur_rt)->m_name.length == len) &&
+ (my_strnncoll(&my_charset_latin1,
+ (const uchar*) (*cur_rt)->m_name.str, len,
+ (const uchar*) name, len) == 0))
+ return *cur_rt;
}
- return NULL;
+ return 0;
}
-int Geometry::create_from_wkb(const char *data, uint32 data_len)
+Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer,
+ const char *data, uint32 data_len)
{
uint32 geom_type;
+ Geometry *result;
if (data_len < 1 + 4)
- return 1;
+ return NULL;
data++;
-//FIXME: check byte ordering
+ /*
+ FIXME: check byte ordering
+ Also check if we could replace this with one byte
+ */
geom_type= uint4korr(data);
data+= 4;
- m_vmt= find_class(geom_type);
- if (!m_vmt)
- return -1;
- m_data= data;
- m_data_end= data + data_len;
- return 0;
+ if (!(result= create_by_typeid(buffer, (int) geom_type)))
+ return NULL;
+ result->m_data= data;
+ result->m_data_end= data + data_len;
+ return result;
}
-int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream)
+
+Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer,
+ Gis_read_stream *trs, String *wkt,
+ bool init_stream)
{
- int name_len;
- const char *name = trs->get_next_word(&name_len);
- if (!name)
+ LEX_STRING name;
+ Class_info *ci;
+
+ if (trs->get_next_word(&name))
{
trs->set_error_msg("Geometry name expected");
- return -1;
+ return NULL;
}
- if (!(m_vmt = find_class(name, name_len)))
- return -1;
- if (wkt->reserve(1 + 4, 512))
- return 1;
- wkt->q_append((char)wkbNDR);
- wkt->q_append((uint32)get_class_info()->m_type_id);
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return -1;
- }
- if (init_from_wkt(trs, wkt)) return 1;
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
- return -1;
- }
+ if (!(ci= find_class(name.str, name.length)) ||
+ wkt->reserve(1 + 4, 512))
+ return NULL;
+ (*ci->m_create_func)((void *)buffer);
+ Geometry *result= (Geometry *)buffer;
+
+ wkt->q_append((char) wkb_ndr);
+ wkt->q_append((uint32) result->get_class_info()->m_type_id);
+ if (trs->check_next_symbol('(') ||
+ result->init_from_wkt(trs, wkt) ||
+ trs->check_next_symbol(')'))
+ return NULL;
if (init_stream)
{
- init_from_wkb(wkt->ptr(), wkt->length());
- shift_wkb_header();
+ result->init_from_wkb(wkt->ptr(), wkt->length());
+ result->shift_wkb_header();
}
- return 0;
+ return result;
}
-int Geometry::envelope(String *result) const
+
+bool Geometry::envelope(String *result) const
{
MBR mbr;
+ const char *end;
- get_mbr(&mbr);
-
- if (result->reserve(1+4*3+sizeof(double)*10))
+ if (get_mbr(&mbr, &end) || result->reserve(1+4*3+SIZEOF_STORED_DOUBLE*10))
return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbPolygon);
- result->q_append((uint32)1);
- result->q_append((uint32)5);
+ result->q_append((char) wkb_ndr);
+ result->q_append((uint32) wkb_polygon);
+ result->q_append((uint32) 1);
+ result->q_append((uint32) 5);
result->q_append(mbr.xmin);
result->q_append(mbr.ymin);
result->q_append(mbr.xmax);
@@ -154,29 +192,151 @@ int Geometry::envelope(String *result) const
return 0;
}
+
+/*
+ Create a point from data.
+
+ SYNPOSIS
+ create_point()
+ result Put result here
+ data Data for point is here.
+
+ RETURN
+ 0 ok
+ 1 Can't reallocate 'result'
+*/
+
+bool Geometry::create_point(String *result, const char *data) const
+{
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2) ||
+ result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
+ return 1;
+ result->q_append((char) wkb_ndr);
+ result->q_append((uint32) wkb_point);
+ /* Copy two double in same format */
+ result->q_append(data, SIZEOF_STORED_DOUBLE*2);
+ return 0;
+}
+
+/*
+ Create a point from coordinates.
+
+ SYNPOSIS
+ create_point()
+ result Put result here
+ x x coordinate for point
+ y y coordinate for point
+
+ RETURN
+ 0 ok
+ 1 Can't reallocate 'result'
+*/
+
+bool Geometry::create_point(String *result, double x, double y) const
+{
+ if (result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
+ return 1;
+
+ result->q_append((char) wkb_ndr);
+ result->q_append((uint32) wkb_point);
+ result->q_append(x);
+ result->q_append(y);
+ return 0;
+}
+
+/*
+ Append N points from packed format to text
+
+ SYNOPSIS
+ append_points()
+ txt Append points here
+ n_points Number of points
+ data Packed data
+ offset Offset between points
+
+ RETURN
+ # end of data
+*/
+
+const char *Geometry::append_points(String *txt, uint32 n_points,
+ const char *data, uint32 offset) const
+{
+ while (n_points--)
+ {
+ double d;
+ data+= offset;
+ float8get(d, data);
+ txt->qs_append(d);
+ txt->qs_append(' ');
+ float8get(d, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
+ txt->qs_append(d);
+ txt->qs_append(',');
+ }
+ return data;
+}
+
+
+/*
+ Get most bounding rectangle (mbr) for X points
+
+ SYNOPSIS
+ get_mbr_for_points()
+ mbr MBR (store rectangle here)
+ points Number of points
+ data Packed data
+ offset Offset between points
+
+ RETURN
+ 0 Wrong data
+ # end of data
+*/
+
+const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
+ uint offset) const
+{
+ uint32 points;
+ /* read number of points */
+ if (no_data(data, 4))
+ return 0;
+ points= uint4korr(data);
+ data+= 4;
+
+ if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points))
+ return 0;
+
+ /* Calculate MBR for points */
+ while (points--)
+ {
+ data+= offset;
+ mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
+ }
+ return data;
+}
+
+
/***************************** Point *******************************/
-size_t GPoint::get_data_size() const
+uint32 Gis_point::get_data_size() const
{
return POINT_DATA_SIZE;
}
-int GPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
double x, y;
- if (wkb->reserve(sizeof(double)*2))
- return 1;
- if (trs->get_next_number(&x))
- return 1;
- if (trs->get_next_number(&y))
+ if (trs->get_next_number(&x) || trs->get_next_number(&y) ||
+ wkb->reserve(SIZEOF_STORED_DOUBLE * 2))
return 1;
wkb->q_append(x);
wkb->q_append(y);
-
return 0;
}
-int GPoint::get_data_as_wkt(String *txt) const
+
+bool Gis_point::get_data_as_wkt(String *txt, const char **end) const
{
double x, y;
if (get_xy(&x, &y))
@@ -186,324 +346,260 @@ int GPoint::get_data_as_wkt(String *txt) const
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
+ *end= m_data+ POINT_DATA_SIZE;
return 0;
}
-int GPoint::get_mbr(MBR *mbr) const
+
+bool Gis_point::get_mbr(MBR *mbr, const char **end) const
{
double x, y;
if (get_xy(&x, &y))
return 1;
mbr->add_xy(x, y);
+ *end= m_data+ POINT_DATA_SIZE;
return 0;
}
+const Geometry::Class_info *Gis_point::get_class_info() const
+{
+ return &point_class;
+}
+
+
/***************************** LineString *******************************/
-size_t GLineString::get_data_size() const
+uint32 Gis_line_string::get_data_size() const
{
- uint32 n_points = uint4korr(m_data);
-
- return 4 + n_points*POINT_DATA_SIZE;
+ if (no_data(m_data, 4))
+ return GET_SIZE_ERROR;
+ return 4 + uint4korr(m_data) * POINT_DATA_SIZE;
}
-int GLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_points = 0;
- int np_pos = wkb->length();
- GPoint p;
+ uint32 n_points= 0;
+ uint32 np_pos= wkb->length();
+ Gis_point p;
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_points);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (p.init_from_wkt(trs, wkb))
return 1;
- ++n_points;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else break;
+ n_points++;
+ if (trs->skip_char(',')) // Didn't find ','
+ break;
}
-
- if (n_points<2)
+ if (n_points < 2)
{
trs->set_error_msg("Too few points in LINESTRING");
return 1;
}
-
- wkb->WriteAtPosition(np_pos, n_points);
-
+ wkb->write_at_position(np_pos, n_points);
return 0;
}
-int GLineString::get_data_as_wkt(String *txt) const
+
+bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const
{
uint32 n_points;
- const char *data = m_data;
+ const char *data= m_data;
if (no_data(data, 4))
return 1;
-
- n_points = uint4korr(data);
+ n_points= uint4korr(data);
data += 4;
- if (no_data(data, sizeof(double) * 2 * n_points))
+ if (n_points < 1 ||
+ no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) ||
+ txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
return 1;
- if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
- return 1;
- for (; n_points>0; --n_points)
+ while (n_points--)
{
double x, y;
float8get(x, data);
- data += sizeof(double);
- float8get(y, data);
- data += sizeof(double);
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
txt->qs_append(',');
}
- txt->length(txt->length() - 1);
+ txt->length(txt->length() - 1); // Remove end ','
+ *end= data;
return 0;
}
-int GLineString::get_mbr(MBR *mbr) const
-{
- uint32 n_points;
- const char *data = m_data;
-
- if (no_data(data, 4))
- return 1;
-
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, sizeof(double) * 2 * n_points))
- return 1;
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
-
- return 0;
+bool Gis_line_string::get_mbr(MBR *mbr, const char **end) const
+{
+ return (*end=get_mbr_for_points(mbr, m_data, 0)) == 0;
}
-int GLineString::length(double *len) const
+
+int Gis_line_string::length(double *len) const
{
uint32 n_points;
double prev_x, prev_y;
- const char *data = m_data;
+ const char *data= m_data;
- *len=0;
+ *len= 0; // In case of errors
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- data += 4;
-
- if (no_data(data, sizeof(double) * 2 * n_points))
+ n_points= uint4korr(data);
+ data+= 4;
+ if (n_points < 1 || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1;
- --n_points;
float8get(prev_x, data);
- data += 8;
- float8get(prev_y, data);
- data += 8;
+ float8get(prev_y, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE*2;
- for (; n_points>0; --n_points)
+ while (--n_points)
{
double x, y;
float8get(x, data);
- data += 8;
- float8get(y, data);
- data += 8;
- *len+=sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
- prev_x=x;
- prev_y=y;
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
+ *len+= sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
+ prev_x= x;
+ prev_y= y;
}
return 0;
}
-int GLineString::is_closed(int *closed) const
+int Gis_line_string::is_closed(int *closed) const
{
uint32 n_points;
double x1, y1, x2, y2;
-
- const char *data = m_data;
+ const char *data= m_data;
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, (8+8) * n_points))
+ n_points= uint4korr(data);
+ data+= 4;
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1;
+
+ /* Get first point */
float8get(x1, data);
- data += 8;
- float8get(y1, data);
- data += 8 + (n_points-2)*POINT_DATA_SIZE;
- float8get(x2, data);
- data += 8;
- float8get(y2, data);
+ float8get(y1, data + SIZEOF_STORED_DOUBLE);
- *closed=(x1==x2)&&(y1==y2);
+ /* get last point */
+ data+= SIZEOF_STORED_DOUBLE*2 + (n_points-2)*POINT_DATA_SIZE;
+ float8get(x2, data);
+ float8get(y2, data + SIZEOF_STORED_DOUBLE);
+ *closed= (x1==x2) && (y1==y2);
return 0;
}
-int GLineString::num_points(uint32 *n_points) const
+
+int Gis_line_string::num_points(uint32 *n_points) const
{
- *n_points = uint4korr(m_data);
+ *n_points= uint4korr(m_data);
return 0;
}
-int GLineString::start_point(String *result) const
-{
- const char *data= m_data + 4;
- if (no_data(data, 8 + 8))
- return 1;
-
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
-
- result->q_append((char) wkbNDR);
- result->q_append((uint32) wkbPoint);
- double d;
- float8get(d, data);
- result->q_append(d);
- float8get(d, data + 8);
- result->q_append(d);
- return 0;
+int Gis_line_string::start_point(String *result) const
+{
+ /* +4 is for skipping over number of points */
+ return create_point(result, m_data + 4);
}
-int GLineString::end_point(String *result) const
+
+int Gis_line_string::end_point(String *result) const
{
- const char *data= m_data;
uint32 n_points;
-
- if (no_data(data, 4))
+ if (no_data(m_data, 4))
return 1;
- n_points= uint4korr(data);
-
- data+= 4 + (n_points - 1) * POINT_DATA_SIZE;
-
- if (no_data(data, 8 + 8))
- return 1;
-
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
- result->q_append((char) wkbNDR);
- result->q_append((uint32) wkbPoint);
- double d;
- float8get(d, data);
- result->q_append(d);
- float8get(d, data + 8);
- result->q_append(d);
-
- return 0;
+ n_points= uint4korr(m_data);
+ return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE);
}
-int GLineString::point_n(uint32 num, String *result) const
+int Gis_line_string::point_n(uint32 num, String *result) const
{
- const char *data= m_data;
uint32 n_points;
-
- if (no_data(data, 4))
+ if (no_data(m_data, 4))
return 1;
- n_points= uint4korr(data);
-
+ n_points= uint4korr(m_data);
if ((uint32) (num - 1) >= n_points) // means (num > n_points || num < 1)
return 1;
- data+= 4 + (num - 1) * POINT_DATA_SIZE;
-
- if (no_data(data, 8 + 8))
- return 1;
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
-
- result->q_append((char) wkbNDR);
- result->q_append((uint32) wkbPoint);
- double d;
- float8get(d, data);
- result->q_append(d);
- float8get(d, data + 8);
- result->q_append(d);
+ return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE);
+}
- return 0;
+const Geometry::Class_info *Gis_line_string::get_class_info() const
+{
+ return &linestring_class;
}
+
/***************************** Polygon *******************************/
-size_t GPolygon::get_data_size() const
+uint32 Gis_polygon::get_data_size() const
{
- uint32 n_linear_rings = 0;
- const char *data = m_data;
+ uint32 n_linear_rings;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
+ return GET_SIZE_ERROR;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
- n_linear_rings = uint4korr(data);
- data += 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ while (n_linear_rings--)
{
if (no_data(data, 4))
- return 1;
- data += 4 + uint4korr(data)*POINT_DATA_SIZE;
+ return GET_SIZE_ERROR;
+ data+= 4 + uint4korr(data)*POINT_DATA_SIZE;
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_linear_rings = 0;
- int lr_pos = wkb->length();
+ uint32 n_linear_rings= 0;
+ uint32 lr_pos= wkb->length();
+ int closed;
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_linear_rings);
-
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
- GLineString ls;
- size_t ls_pos=wkb->length();
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
+ Gis_line_string ls;
+ uint32 ls_pos=wkb->length();
+ if (trs->check_next_symbol('(') ||
+ ls.init_from_wkt(trs, wkb) ||
+ trs->check_next_symbol(')'))
return 1;
- }
- if (ls.init_from_wkt(trs, wkb))
- return 1;
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
- return 1;
- }
+
ls.init_from_wkb(wkb->ptr()+ls_pos, wkb->length()-ls_pos);
- int closed;
- ls.is_closed(&closed);
- if (!closed)
+ if (ls.is_closed(&closed) || !closed)
{
trs->set_error_msg("POLYGON's linear ring isn't closed");
return 1;
}
- ++n_linear_rings;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_linear_rings++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(lr_pos, n_linear_rings);
+ wkb->write_at_position(lr_pos, n_linear_rings);
return 0;
}
-int GPolygon::get_data_as_wkt(String *txt) const
+
+bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const
{
uint32 n_linear_rings;
const char *data= m_data;
@@ -514,1059 +610,1045 @@ int GPolygon::get_data_as_wkt(String *txt) const
n_linear_rings= uint4korr(data);
data+= 4;
- for (; n_linear_rings > 0; --n_linear_rings)
+ while (n_linear_rings--)
{
+ uint32 n_points;
if (no_data(data, 4))
return 1;
- uint32 n_points= uint4korr(data);
+ n_points= uint4korr(data);
data+= 4;
- if (no_data(data, (8 + 8) * n_points))
- return 1;
-
- if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+ if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
+ txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + 8);
- txt->qs_append(d);
- txt->qs_append(',');
-
- data+= 8 + 8;
- }
- (*txt) [txt->length() - 1]= ')';
+ data= append_points(txt, n_points, data, 0);
+ (*txt) [txt->length() - 1]= ')'; // Replace end ','
txt->qs_append(',');
}
- txt->length(txt->length() - 1);
+ txt->length(txt->length() - 1); // Remove end ','
+ *end= data;
return 0;
}
-int GPolygon::get_mbr(MBR *mbr) const
+
+bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_linear_rings;
+ const char *data= m_data;
- const char *data = m_data;
if (no_data(data, 4))
return 1;
- n_linear_rings = uint4korr(data);
- data += 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ n_linear_rings= uint4korr(data);
+ data+= 4;
+
+ while (n_linear_rings--)
{
- if (no_data(data, 4))
- return 1;
- uint32 n_points = uint4korr(data);
- data += 4;
- if (no_data(data, (8+8) * n_points))
+ if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1;
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
}
+ *end= data;
return 0;
}
-int GPolygon::area(double *ar) const
+
+int Gis_polygon::area(double *ar, const char **end_of_data) const
{
uint32 n_linear_rings;
- double result = -1.0;
+ double result= -1.0;
+ const char *data= m_data;
- const char *data = m_data;
if (no_data(data, 4))
return 1;
- n_linear_rings = uint4korr(data);
- data += 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ n_linear_rings= uint4korr(data);
+ data+= 4;
+
+ while (n_linear_rings--)
{
double prev_x, prev_y;
- double lr_area=0;
+ double lr_area= 0;
+ uint32 n_points;
+
if (no_data(data, 4))
return 1;
- uint32 n_points = uint4korr(data);
- if (no_data(data, (8+8) * n_points))
+ n_points= uint4korr(data);
+ if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1;
float8get(prev_x, data+4);
- float8get(prev_y, data+(4+8));
- data += (4+8+8);
+ float8get(prev_y, data+(4+SIZEOF_STORED_DOUBLE));
+ data+= (4+SIZEOF_STORED_DOUBLE*2);
- --n_points;
- for (; n_points>0; --n_points)
+ while (--n_points) // One point is already read
{
double x, y;
float8get(x, data);
- float8get(y, data + 8);
- lr_area+=(prev_x+x)*(prev_y-y);
- prev_x=x;
- prev_y=y;
- data += (8+8);
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= (SIZEOF_STORED_DOUBLE*2);
+ /* QQ: Is the following prev_x+x right ? */
+ lr_area+= (prev_x + x)* (prev_y - y);
+ prev_x= x;
+ prev_y= y;
}
- lr_area=fabs(lr_area)/2;
- if (result==-1) result=lr_area;
- else result-=lr_area;
+ lr_area= fabs(lr_area)/2;
+ if (result == -1.0)
+ result= lr_area;
+ else
+ result-= lr_area;
}
- *ar=fabs(result);
+ *ar= fabs(result);
+ *end_of_data= data;
return 0;
}
-int GPolygon::exterior_ring(String *result) const
+int Gis_polygon::exterior_ring(String *result) const
{
- uint32 n_points;
- const char *data = m_data + 4; // skip n_linerings
+ uint32 n_points, length;
+ const char *data= m_data + 4; // skip n_linerings
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, n_points * POINT_DATA_SIZE))
- return 1;
-
- if (result->reserve(1+4+4+ n_points * POINT_DATA_SIZE))
+ n_points= uint4korr(data);
+ data+= 4;
+ length= n_points * POINT_DATA_SIZE;
+ if (no_data(data, length) || result->reserve(1+4+4+ length))
return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbLineString);
+ result->q_append((char) wkb_ndr);
+ result->q_append((uint32) wkb_linestring);
result->q_append(n_points);
result->q_append(data, n_points * POINT_DATA_SIZE);
-
return 0;
}
-int GPolygon::num_interior_ring(uint32 *n_int_rings) const
+
+int Gis_polygon::num_interior_ring(uint32 *n_int_rings) const
{
- const char *data = m_data;
- if (no_data(data, 4))
+ if (no_data(m_data, 4))
return 1;
- *n_int_rings = uint4korr(data);
- --(*n_int_rings);
-
+ *n_int_rings= uint4korr(m_data)-1;
return 0;
}
-int GPolygon::interior_ring_n(uint32 num, String *result) const
+
+int Gis_polygon::interior_ring_n(uint32 num, String *result) const
{
- const char *data = m_data;
+ const char *data= m_data;
uint32 n_linear_rings;
uint32 n_points;
+ uint32 points_size;
if (no_data(data, 4))
return 1;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
- n_linear_rings = uint4korr(data);
- data += 4;
- if ((num >= n_linear_rings) || (num < 1))
- return -1;
+ if (num >= n_linear_rings || num < 1)
+ return 1;
- for (; num > 0; --num)
+ while (num--)
{
if (no_data(data, 4))
return 1;
- data += 4 + uint4korr(data) * POINT_DATA_SIZE;
+ data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
}
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- int points_size = n_points * POINT_DATA_SIZE;
- data += 4;
- if (no_data(data, points_size))
- return 1;
-
- if (result->reserve(1+4+4+ points_size))
+ n_points= uint4korr(data);
+ points_size= n_points * POINT_DATA_SIZE;
+ data+= 4;
+ if (no_data(data, points_size) || result->reserve(1+4+4+ points_size))
return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbLineString);
+ result->q_append((char) wkb_ndr);
+ result->q_append((uint32) wkb_linestring);
result->q_append(n_points);
result->q_append(data, points_size);
return 0;
}
-int GPolygon::centroid_xy(double *x, double *y) const
+
+int Gis_polygon::centroid_xy(double *x, double *y) const
{
uint32 n_linear_rings;
- uint32 i;
double res_area, res_cx, res_cy;
- const char *data = m_data;
+ const char *data= m_data;
+ bool first_loop= 1;
LINT_INIT(res_area);
LINT_INIT(res_cx);
LINT_INIT(res_cy);
if (no_data(data, 4))
return 1;
- n_linear_rings = uint4korr(data);
- data += 4;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
- for (i = 0; i < n_linear_rings; ++i)
+ while (n_linear_rings--)
{
- if (no_data(data, 4))
- return 1;
- uint32 n_points = uint4korr(data);
+ uint32 n_points, org_n_points;
double prev_x, prev_y;
- double cur_area = 0;
- double cur_cx = 0;
- double cur_cy = 0;
+ double cur_area= 0;
+ double cur_cx= 0;
+ double cur_cy= 0;
- data += 4;
- if (no_data(data, (8+8) * n_points))
+ if (no_data(data, 4))
+ return 1;
+ org_n_points= n_points= uint4korr(data);
+ data+= 4;
+ if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1;
float8get(prev_x, data);
- float8get(prev_y, data+8);
- data += (8+8);
+ float8get(prev_y, data+SIZEOF_STORED_DOUBLE);
+ data+= (SIZEOF_STORED_DOUBLE*2);
- uint32 n = n_points - 1;
- for (; n > 0; --n)
+ while (--n_points) // One point is already read
{
double x, y;
float8get(x, data);
- float8get(y, data + 8);
-
- cur_area += (prev_x + x) * (prev_y - y);
- cur_cx += x;
- cur_cy += y;
- prev_x = x;
- prev_y = y;
- data += (8+8);
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= (SIZEOF_STORED_DOUBLE*2);
+ /* QQ: Is the following prev_x+x right ? */
+ cur_area+= (prev_x + x) * (prev_y - y);
+ cur_cx+= x;
+ cur_cy+= y;
+ prev_x= x;
+ prev_y= y;
}
- cur_area = fabs(cur_area) / 2;
- cur_cx = cur_cx / (n_points - 1);
- cur_cy = cur_cy / (n_points - 1);
+ cur_area= fabs(cur_area) / 2;
+ cur_cx= cur_cx / (org_n_points - 1);
+ cur_cy= cur_cy / (org_n_points - 1);
- if (i)
+ if (!first_loop)
{
- double d_area = res_area - cur_area;
+ double d_area= res_area - cur_area;
if (d_area <= 0)
return 1;
- res_cx = (res_area * res_cx - cur_area * cur_cx) / d_area;
- res_cy = (res_area * res_cy - cur_area * cur_cy) / d_area;
+ res_cx= (res_area * res_cx - cur_area * cur_cx) / d_area;
+ res_cy= (res_area * res_cy - cur_area * cur_cy) / d_area;
}
else
{
- res_area = cur_area;
- res_cx = cur_cx;
- res_cy = cur_cy;
+ first_loop= 0;
+ res_area= cur_area;
+ res_cx= cur_cx;
+ res_cy= cur_cy;
}
}
- *x = res_cx;
- *y = res_cy;
-
+ *x= res_cx;
+ *y= res_cy;
return 0;
}
-int GPolygon::centroid(String *result) const
+
+int Gis_polygon::centroid(String *result) const
{
double x, y;
-
- this->centroid_xy(&x, &y);
- if (result->reserve(1 + 4 + sizeof(double) * 2))
+ if (centroid_xy(&x, &y))
return 1;
+ return create_point(result, x, y);
+}
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbPoint);
- result->q_append(x);
- result->q_append(y);
-
- return 0;
+const Geometry::Class_info *Gis_polygon::get_class_info() const
+{
+ return &polygon_class;
}
/***************************** MultiPoint *******************************/
-size_t GMultiPoint::get_data_size() const
+uint32 Gis_multi_point::get_data_size() const
{
+ if (no_data(m_data, 4))
+ return GET_SIZE_ERROR;
return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE);
}
-int GMultiPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_points = 0;
- int np_pos = wkb->length();
- GPoint p;
+ uint32 n_points= 0;
+ uint32 np_pos= wkb->length();
+ Gis_point p;
if (wkb->reserve(4, 512))
return 1;
- wkb->q_append((uint32)n_points);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (wkb->reserve(1+4, 512))
return 1;
- wkb->q_append((char)wkbNDR);
- wkb->q_append((uint32)wkbPoint);
+ wkb->q_append((char) wkb_ndr);
+ wkb->q_append((uint32) wkb_point);
if (p.init_from_wkt(trs, wkb))
return 1;
- ++n_points;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_points++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(np_pos, n_points);
-
+ wkb->write_at_position(np_pos, n_points); // Store number of found points
return 0;
}
-int GMultiPoint::get_data_as_wkt(String *txt) const
+
+bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const
{
uint32 n_points;
- const char *data= m_data;
- if (no_data(data, 4))
- return 1;
-
- n_points= uint4korr(data);
- data+= 4;
- if (no_data(data, n_points * (8 + 8 + WKB_HEADER_SIZE)))
+ if (no_data(m_data, 4))
return 1;
- if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+ n_points= uint4korr(m_data);
+ if (no_data(m_data+4,
+ n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) ||
+ txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
-
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data + WKB_HEADER_SIZE);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + WKB_HEADER_SIZE + 8);
- txt->qs_append(d);
- txt->qs_append(',');
- data+= WKB_HEADER_SIZE + 8 + 8;
- }
- txt->length(txt->length()-1);
+ *end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE);
+ txt->length(txt->length()-1); // Remove end ','
return 0;
}
-int GMultiPoint::get_mbr(MBR *mbr) const
+
+bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const
{
- uint32 n_points;
- const char *data = m_data;
- if (no_data(data, 4))
- return 1;
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, n_points * (8+8+WKB_HEADER_SIZE)))
- return 1;
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data + WKB_HEADER_SIZE, data + 8 + WKB_HEADER_SIZE);
- data += (8+8+WKB_HEADER_SIZE);
- }
- return 0;
+ return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 0;
}
-int GMultiPoint::num_geometries(uint32 *num) const
+
+int Gis_multi_point::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ *num= uint4korr(m_data);
return 0;
}
-int GMultiPoint::geometry_n(uint32 num, String *result) const
+
+int Gis_multi_point::geometry_n(uint32 num, String *result) const
{
const char *data= m_data;
uint32 n_points;
+
if (no_data(data, 4))
return 1;
n_points= uint4korr(data);
- data+= 4;
- if ((num > n_points) || (num < 1))
- return -1;
- data+= (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
- if (result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
+ data+= 4+ (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
+
+ if (num > n_points || num < 1 ||
+ no_data(data, WKB_HEADER_SIZE + POINT_DATA_SIZE) ||
+ result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
return 1;
- result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
+ result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
return 0;
}
+const Geometry::Class_info *Gis_multi_point::get_class_info() const
+{
+ return &multipoint_class;
+}
+
+
/***************************** MultiLineString *******************************/
-size_t GMultiLineString::get_data_size() const
+uint32 Gis_multi_line_string::get_data_size() const
{
- uint32 n_line_strings = 0;
- const char *data = m_data;
+ uint32 n_line_strings;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
- n_line_strings = uint4korr(data);
- data += 4;
+ return GET_SIZE_ERROR;
+ n_line_strings= uint4korr(data);
+ data+= 4;
- for (; n_line_strings>0; --n_line_strings)
+ while (n_line_strings--)
{
if (no_data(data, WKB_HEADER_SIZE + 4))
- return 1;
- data += WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) * POINT_DATA_SIZE;
+ return GET_SIZE_ERROR;
+ data+= (WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) *
+ POINT_DATA_SIZE);
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GMultiLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_line_strings = 0;
- int ls_pos = wkb->length();
+ uint32 n_line_strings= 0;
+ uint32 ls_pos= wkb->length();
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_line_strings);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
- GLineString ls;
+ Gis_line_string ls;
if (wkb->reserve(1+4, 512))
return 1;
- wkb->q_append((char)wkbNDR);
- wkb->q_append((uint32)wkbLineString);
-
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return 1;
- }
- if (ls.init_from_wkt(trs, wkb))
- return 1;
+ wkb->q_append((char) wkb_ndr);
+ wkb->q_append((uint32) wkb_linestring);
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
+ if (trs->check_next_symbol('(') ||
+ ls.init_from_wkt(trs, wkb) ||
+ trs->check_next_symbol(')'))
return 1;
- }
- ++n_line_strings;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_line_strings++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(ls_pos, n_line_strings);
-
+ wkb->write_at_position(ls_pos, n_line_strings);
return 0;
}
-int GMultiLineString::get_data_as_wkt(String *txt) const
+
+bool Gis_multi_line_string::get_data_as_wkt(String *txt,
+ const char **end) const
{
uint32 n_line_strings;
const char *data= m_data;
+
if (no_data(data, 4))
return 1;
n_line_strings= uint4korr(data);
data+= 4;
- for (; n_line_strings > 0; --n_line_strings)
+
+ while (n_line_strings--)
{
+ uint32 n_points;
if (no_data(data, (WKB_HEADER_SIZE + 4)))
return 1;
- uint32 n_points= uint4korr(data + WKB_HEADER_SIZE);
+ n_points= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
- if (no_data(data, n_points * (8 + 8)))
- return 1;
-
- if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+ if (no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
+ txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + 8);
- txt->qs_append(d);
- txt->qs_append(',');
- data+= 8 + 8;
- }
- (*txt) [txt->length() - 1] = ')';
+ data= append_points(txt, n_points, data, 0);
+ (*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
txt->length(txt->length() - 1);
+ *end= data;
return 0;
}
-int GMultiLineString::get_mbr(MBR *mbr) const
+
+bool Gis_multi_line_string::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_line_strings;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_line_strings = uint4korr(data);
- data += 4;
+ n_line_strings= uint4korr(data);
+ data+= 4;
- for (; n_line_strings>0; --n_line_strings)
+ while (n_line_strings--)
{
- if (no_data(data, WKB_HEADER_SIZE + 4))
- return 1;
- uint32 n_points = uint4korr(data + WKB_HEADER_SIZE);
- data += 4+WKB_HEADER_SIZE;
- if (no_data(data, (8+8)*n_points))
+ data+= WKB_HEADER_SIZE;
+ if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1;
-
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
}
+ *end= data;
return 0;
}
-int GMultiLineString::num_geometries(uint32 *num) const
+
+int Gis_multi_line_string::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ *num= uint4korr(m_data);
return 0;
}
-int GMultiLineString::geometry_n(uint32 num, String *result) const
+
+int Gis_multi_line_string::geometry_n(uint32 num, String *result) const
{
- uint32 n_line_strings;
+ uint32 n_line_strings, n_points, length;
const char *data= m_data;
+
if (no_data(data, 4))
return 1;
n_line_strings= uint4korr(data);
data+= 4;
if ((num > n_line_strings) || (num < 1))
- return -1;
+ return 1;
- for (; num > 0; --num)
+ for (;;)
{
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
- uint32 n_points= uint4korr(data + WKB_HEADER_SIZE);
- if (num == 1)
- {
- if (result->reserve(WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points))
- return 1;
- result->q_append(data, WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE *n_points);
+ n_points= uint4korr(data + WKB_HEADER_SIZE);
+ length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points;
+ if (no_data(data, length))
+ return 1;
+ if (!--num)
break;
- }
- else
- {
- data+= WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points;
- }
+ data+= length;
}
- return 0;
+ return result->append(data, length, (uint32) 0);
}
-int GMultiLineString::length(double *len) const
+
+int Gis_multi_line_string::length(double *len) const
{
uint32 n_line_strings;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_line_strings = uint4korr(data);
- data += 4;
+ n_line_strings= uint4korr(data);
+ data+= 4;
+
*len=0;
- for (; n_line_strings>0; --n_line_strings)
+ while (n_line_strings--)
{
double ls_len;
- GLineString ls;
- data += WKB_HEADER_SIZE;
- ls.init_from_wkb(data, m_data_end - data);
+ Gis_line_string ls;
+ data+= WKB_HEADER_SIZE;
+ ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.length(&ls_len))
return 1;
- *len+=ls_len;
- data += ls.get_data_size();
+ *len+= ls_len;
+ /*
+ We know here that ls was ok, so we can call the trivial function
+ Gis_line_string::get_data_size without error checking
+ */
+ data+= ls.get_data_size();
}
return 0;
}
-int GMultiLineString::is_closed(int *closed) const
+
+int Gis_multi_line_string::is_closed(int *closed) const
{
uint32 n_line_strings;
- const char *data = m_data;
- if (no_data(data, 1))
+ const char *data= m_data;
+
+ if (no_data(data, 4 + WKB_HEADER_SIZE))
return 1;
- n_line_strings = uint4korr(data);
- data += 4 + WKB_HEADER_SIZE;
- for (; n_line_strings>0; --n_line_strings)
+ n_line_strings= uint4korr(data);
+ data+= 4 + WKB_HEADER_SIZE;
+
+ while (n_line_strings--)
{
- GLineString ls;
- ls.init_from_wkb(data, m_data_end - data);
+ Gis_line_string ls;
+ if (no_data(data, 0))
+ return 1;
+ ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.is_closed(closed))
return 1;
if (!*closed)
return 0;
- data += ls.get_data_size() + WKB_HEADER_SIZE;
+ /*
+ We know here that ls was ok, so we can call the trivial function
+ Gis_line_string::get_data_size without error checking
+ */
+ data+= ls.get_data_size() + WKB_HEADER_SIZE;
}
return 0;
}
+const Geometry::Class_info *Gis_multi_line_string::get_class_info() const
+{
+ return &multilinestring_class;
+}
+
+
/***************************** MultiPolygon *******************************/
-size_t GMultiPolygon::get_data_size() const
+uint32 Gis_multi_polygon::get_data_size() const
{
uint32 n_polygons;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ return GET_SIZE_ERROR;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
+ uint32 n_linear_rings;
if (no_data(data, 4 + WKB_HEADER_SIZE))
- return 1;
- uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
- data += 4 + WKB_HEADER_SIZE;
+ return GET_SIZE_ERROR;
+
+ n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
+ data+= 4 + WKB_HEADER_SIZE;
- for (; n_linear_rings > 0; --n_linear_rings)
+ while (n_linear_rings--)
{
- data += 4 + uint4korr(data) * POINT_DATA_SIZE;
+ if (no_data(data, 4))
+ return GET_SIZE_ERROR;
+ data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
}
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GMultiPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_polygons = 0;
- int np_pos = wkb->length();
- GPolygon p;
+ uint32 n_polygons= 0;
+ int np_pos= wkb->length();
+ Gis_polygon p;
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_polygons);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (wkb->reserve(1+4, 512))
return 1;
- wkb->q_append((char)wkbNDR);
- wkb->q_append((uint32)wkbPolygon);
+ wkb->q_append((char) wkb_ndr);
+ wkb->q_append((uint32) wkb_polygon);
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return 1;
- }
- if (p.init_from_wkt(trs, wkb))
- return 1;
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
+ if (trs->check_next_symbol('(') ||
+ p.init_from_wkt(trs, wkb) ||
+ trs->check_next_symbol(')'))
return 1;
- }
- ++n_polygons;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_polygons++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(np_pos, n_polygons);
+ wkb->write_at_position(np_pos, n_polygons);
return 0;
}
-int GMultiPolygon::get_data_as_wkt(String *txt) const
+
+bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const
{
uint32 n_polygons;
const char *data= m_data;
+
if (no_data(data, 4))
return 1;
n_polygons= uint4korr(data);
data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
- if (no_data(data, 4 + WKB_HEADER_SIZE))
- return 1;
- data+= WKB_HEADER_SIZE;
- uint32 n_linear_rings= uint4korr(data);
- data+= 4;
-
- if (txt->reserve(1, 512))
+ uint32 n_linear_rings;
+ if (no_data(data, 4 + WKB_HEADER_SIZE) ||
+ txt->reserve(1, 512))
return 1;
+ n_linear_rings= uint4korr(data+WKB_HEADER_SIZE);
+ data+= 4 + WKB_HEADER_SIZE;
txt->q_append('(');
- for (; n_linear_rings>0; --n_linear_rings)
+
+ while (n_linear_rings--)
{
if (no_data(data, 4))
return 1;
uint32 n_points= uint4korr(data);
data+= 4;
- if (no_data(data, (8 + 8) * n_points)) return 1;
-
- if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
- 512)) return 1;
+ if (no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
+ txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
+ 512))
+ return 1;
txt->qs_append('(');
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + 8);
- txt->qs_append(d);
- txt->qs_append(',');
- data+= 8 + 8;
- }
- (*txt) [txt->length() - 1] = ')';
+ data= append_points(txt, n_points, data, 0);
+ (*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
- (*txt) [txt->length() - 1] = ')';
+ (*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
txt->length(txt->length() - 1);
+ *end= data;
return 0;
}
-int GMultiPolygon::get_mbr(MBR *mbr) const
+
+bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_polygons;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
+ uint32 n_linear_rings;
if (no_data(data, 4+WKB_HEADER_SIZE))
return 1;
- uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
- data += WKB_HEADER_SIZE + 4;
+ n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
+ data+= WKB_HEADER_SIZE + 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ while (n_linear_rings--)
{
- if (no_data(data, 4))
- return 1;
- uint32 n_points = uint4korr(data);
- data += 4;
- if (no_data(data, (8+8)*n_points))
- return 1;
-
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
+ if (!(data= get_mbr_for_points(mbr, data, 0)))
+ return 1;
}
}
+ *end= data;
return 0;
}
-int GMultiPolygon::num_geometries(uint32 *num) const
+
+int Gis_multi_polygon::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ *num= uint4korr(m_data);
return 0;
}
-int GMultiPolygon::geometry_n(uint32 num, String *result) const
+
+int Gis_multi_polygon::geometry_n(uint32 num, String *result) const
{
uint32 n_polygons;
- const char *data= m_data, *polygon_n;
- LINT_INIT(polygon_n);
+ const char *data= m_data, *start_of_polygon;
if (no_data(data, 4))
return 1;
n_polygons= uint4korr(data);
data+= 4;
- if ((num > n_polygons) || (num < 1))
+ if (num > n_polygons || num < 1)
return -1;
- for (; num > 0; --num)
+ do
{
+ uint32 n_linear_rings;
+ start_of_polygon= data;
+
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
- uint32 n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
-
- if (num == 1)
- polygon_n= data;
+ n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
- for (; n_linear_rings > 0; --n_linear_rings)
+
+ while (n_linear_rings--)
{
+ uint32 n_points;
if (no_data(data, 4))
return 1;
- uint32 n_points= uint4korr(data);
+ n_points= uint4korr(data);
data+= 4 + POINT_DATA_SIZE * n_points;
}
- if (num == 1)
- {
- if (result->reserve(data - polygon_n))
- return -1;
- result->q_append(polygon_n, data - polygon_n);
- break;
- }
- }
- return 0;
+ } while (--num);
+ if (no_data(data, 0)) // We must check last segment
+ return 1;
+ return result->append(start_of_polygon, (uint32) (data - start_of_polygon),
+ (uint32) 0);
}
-int GMultiPolygon::area(double *ar) const
+
+int Gis_multi_polygon::area(double *ar, const char **end_of_data) const
{
uint32 n_polygons;
- const char *data = m_data;
- double result = 0;
+ const char *data= m_data;
+ double result= 0;
+
if (no_data(data, 4))
return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
double p_area;
+ Gis_polygon p;
- GPolygon p;
- data += WKB_HEADER_SIZE;
- p.init_from_wkb(data, m_data_end - data);
- if (p.area(&p_area))
+ data+= WKB_HEADER_SIZE;
+ p.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (p.area(&p_area, &data))
return 1;
- result += p_area;
- data += p.get_data_size();
+ result+= p_area;
}
- *ar = result;
+ *ar= result;
+ *end_of_data= data;
return 0;
}
-int GMultiPolygon::centroid(String *result) const
+
+int Gis_multi_polygon::centroid(String *result) const
{
uint32 n_polygons;
- uint i;
- GPolygon p;
+ bool first_loop= 1;
+ Gis_polygon p;
double res_area, res_cx, res_cy;
double cur_area, cur_cx, cur_cy;
+ const char *data= m_data;
LINT_INIT(res_area);
LINT_INIT(res_cx);
LINT_INIT(res_cy);
- const char *data = m_data;
if (no_data(data, 4))
return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (i = 0; i < n_polygons; ++i)
+ while (n_polygons--)
{
- data += WKB_HEADER_SIZE;
- p.init_from_wkb(data, m_data_end - data);
- if (p.area(&cur_area))
- return 1;
-
- if (p.centroid_xy(&cur_cx, &cur_cy))
+ data+= WKB_HEADER_SIZE;
+ p.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (p.area(&cur_area, &data) ||
+ p.centroid_xy(&cur_cx, &cur_cy))
return 1;
- if (i)
+ if (!first_loop)
{
- double sum_area = res_area + cur_area;
- res_cx = (res_area * res_cx + cur_area * cur_cx) / sum_area;
- res_cy = (res_area * res_cy + cur_area * cur_cy) / sum_area;
+ double sum_area= res_area + cur_area;
+ res_cx= (res_area * res_cx + cur_area * cur_cx) / sum_area;
+ res_cy= (res_area * res_cy + cur_area * cur_cy) / sum_area;
}
else
{
- res_area = cur_area;
- res_cx = cur_cx;
- res_cy = cur_cy;
+ first_loop= 0;
+ res_area= cur_area;
+ res_cx= cur_cx;
+ res_cy= cur_cy;
}
-
- data += p.get_data_size();
}
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbPoint);
- result->q_append(res_cx);
- result->q_append(res_cy);
+ return create_point(result, res_cx, res_cy);
+}
- return 0;
+const Geometry::Class_info *Gis_multi_polygon::get_class_info() const
+{
+ return &multipolygon_class;
}
-/***************************** GeometryCollection *******************************/
-size_t GGeometryCollection::get_data_size() const
+/************************* GeometryCollection ****************************/
+
+uint32 Gis_geometry_collection::get_data_size() const
{
uint32 n_objects;
- const char *data = m_data;
+ const char *data= m_data;
+ Geometry_buffer buffer;
+ Geometry *geom;
+
if (no_data(data, 4))
- return 1;
- n_objects = uint4korr(data);
- data += 4;
+ return GET_SIZE_ERROR;
+ n_objects= uint4korr(data);
+ data+= 4;
- for (; n_objects>0; --n_objects)
+ while (n_objects--)
{
- if (no_data(data, WKB_HEADER_SIZE))
- return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
-
- Geometry geom;
+ uint32 wkb_type,object_size;
- if (geom.init(wkb_type))
- return 0;
+ if (no_data(data, WKB_HEADER_SIZE))
+ return GET_SIZE_ERROR;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
- geom.init_from_wkb(data, m_data_end - data);
- size_t object_size=geom.get_data_size();
- data += object_size;
+ if (!(geom= create_by_typeid(&buffer, wkb_type)))
+ return GET_SIZE_ERROR;
+ geom->init_from_wkb(data, (uint) (m_data_end - data));
+ if ((object_size= geom->get_data_size()) == GET_SIZE_ERROR)
+ return GET_SIZE_ERROR;
+ data+= object_size;
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GGeometryCollection::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_objects = 0;
- int no_pos = wkb->length();
- Geometry g;
+ uint32 n_objects= 0;
+ uint32 no_pos= wkb->length();
+ Geometry_buffer buffer;
+ Geometry *g;
if (wkb->reserve(4, 512))
return 1;
- wkb->q_append((uint32)n_objects);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
- if (g.create_from_wkt(trs, wkb))
+ if (!(g= create_from_wkt(&buffer, trs, wkb)))
return 1;
- if (g.get_class_info()->m_type_id==wkbGeometryCollection)
+ if (g->get_class_info()->m_type_id == wkb_geometrycollection)
{
trs->set_error_msg("Unexpected GEOMETRYCOLLECTION");
return 1;
}
- ++n_objects;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else break;
+ n_objects++;
+ if (trs->skip_char(',')) // Didn't find ','
+ break;
}
- wkb->WriteAtPosition(no_pos, n_objects);
+ wkb->write_at_position(no_pos, n_objects);
return 0;
}
-int GGeometryCollection::get_data_as_wkt(String *txt) const
+
+bool Gis_geometry_collection::get_data_as_wkt(String *txt,
+ const char **end) const
{
uint32 n_objects;
- const char *data = m_data;
- Geometry geom;
+ Geometry_buffer buffer;
+ Geometry *geom;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
+ n_objects= uint4korr(data);
+ data+= 4;
- for (; n_objects>0; --n_objects)
+ while (n_objects--)
{
+ uint32 wkb_type;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
- if (geom.init(wkb_type))
+ if (!(geom= create_by_typeid(&buffer, wkb_type)))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- if (geom.as_wkt(txt))
+ geom->init_from_wkb(data, (uint) (m_data_end - data));
+ if (geom->as_wkt(txt, &data))
+ return 1;
+ if (txt->append(",", 1, 512))
return 1;
- data += geom.get_data_size();
- txt->reserve(1, 512);
- txt->q_append(',');
}
txt->length(txt->length() - 1);
+ *end= data;
return 0;
}
-int GGeometryCollection::get_mbr(MBR *mbr) const
+
+bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_objects;
- const char *data = m_data;
+ const char *data= m_data;
+ Geometry_buffer buffer;
+ Geometry *geom;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
- for (; n_objects>0; --n_objects)
+ n_objects= uint4korr(data);
+ data+= 4;
+
+ while (n_objects--)
{
+ uint32 wkb_type;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
- Geometry geom;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
- if (geom.init(wkb_type))
+ if (!(geom= create_by_typeid(&buffer, wkb_type)))
+ return 1;
+ geom->init_from_wkb(data, (uint32) (m_data_end - data));
+ if (geom->get_mbr(mbr, &data))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- geom.get_mbr(mbr);
- data += geom.get_data_size();
}
+ *end= data;
return 0;
}
-int GGeometryCollection::num_geometries(uint32 *num) const
+
+int Gis_geometry_collection::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ if (no_data(m_data, 4))
+ return 1;
+ *num= uint4korr(m_data);
return 0;
}
-int GGeometryCollection::geometry_n(uint32 num, String *result) const
+
+int Gis_geometry_collection::geometry_n(uint32 num, String *result) const
{
- const char *data = m_data;
- uint32 n_objects;
+ uint32 n_objects, wkb_type, length;
+ const char *data= m_data;
+ Geometry_buffer buffer;
+ Geometry *geom;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
+ n_objects= uint4korr(data);
+ data+= 4;
+ if (num > n_objects || num < 1)
+ return 1;
- if ((num > n_objects) || (num < 1))
- {
- return -1;
- }
- for (; num > 0; --num)
+ do
{
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
- Geometry geom;
- if (geom.init(wkb_type))
+ if (!(geom= create_by_typeid(&buffer, wkb_type)))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- if (num == 1)
- {
- if (result->reserve(1+4+geom.get_data_size()))
- return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkb_type);
- result->q_append(data, geom.get_data_size());
- break;
- }
- else
- {
- data += geom.get_data_size();
- }
- }
+ geom->init_from_wkb(data, (uint) (m_data_end - data));
+ if ((length= geom->get_data_size()) == GET_SIZE_ERROR)
+ return 1;
+ data+= length;
+ } while (--num);
+
+ /* Copy found object to result */
+ if (result->reserve(1+4+length))
+ return 1;
+ result->q_append((char) wkb_ndr);
+ result->q_append((uint32) wkb_type);
+ result->q_append(data-length, length); // data-length = start_of_data
return 0;
}
-int GGeometryCollection::dimension(uint32 *dim) const
+
+/*
+ Return dimension for object
+
+ SYNOPSIS
+ dimension()
+ res_dim Result dimension
+ end End of object will be stored here. May be 0 for
+ simple objects!
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const
{
uint32 n_objects;
- *dim = 0;
- const char *data = m_data;
+ const char *data= m_data;
+ Geometry_buffer buffer;
+ Geometry *geom;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
+ n_objects= uint4korr(data);
+ data+= 4;
- for (; n_objects > 0; --n_objects)
+ *res_dim= 0;
+ while (n_objects--)
{
+ uint32 wkb_type, length, dim;
+ const char *end_data;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
-
- uint32 d;
-
- Geometry geom;
- if (geom.init(wkb_type))
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
+ if (!(geom= create_by_typeid(&buffer, wkb_type)))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- if (geom.dimension(&d))
+ geom->init_from_wkb(data, (uint32) (m_data_end - data));
+ if (geom->dimension(&dim, &end_data))
return 1;
-
- if (d > *dim)
- *dim = d;
- data += geom.get_data_size();
+ set_if_bigger(*res_dim, dim);
+ if (end_data) // Complex object
+ data= end_data;
+ else if ((length= geom->get_data_size()) == GET_SIZE_ERROR)
+ return 1;
+ else
+ data+= length;
}
+ *end= data;
return 0;
}
-/***************************** /objects *******************************/
+const Geometry::Class_info *Gis_geometry_collection::get_class_info() const
+{
+ return &geometrycollection_class;
+}
+
diff --git a/sql/spatial.h b/sql/spatial.h
index 5fda257f1b1..cf07b364bb3 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -17,118 +17,80 @@
#ifndef _spatial_h
#define _spatial_h
-const uint POINT_DATA_SIZE = 8+8;
-const uint WKB_HEADER_SIZE = 1+4;
+const uint SRID_SIZE= 4;
+const uint SIZEOF_STORED_DOUBLE= 8;
+const uint POINT_DATA_SIZE= SIZEOF_STORED_DOUBLE*2;
+const uint WKB_HEADER_SIZE= 1+4;
+const uint32 GET_SIZE_ERROR= ((uint32) -1);
-struct stPoint2D
+struct st_point_2d
{
double x;
double y;
};
-struct stLinearRing
+struct st_linear_ring
{
- size_t n_points;
- stPoint2D points;
+ uint32 n_points;
+ st_point_2d points;
};
/***************************** MBR *******************************/
+
+/*
+ It's ok that a lot of the functions are inline as these are only used once
+ in MySQL
+*/
+
struct MBR
{
+ double xmin, ymin, xmax, ymax;
+
MBR()
{
- xmin=DBL_MAX;
- ymin=DBL_MAX;
- xmax=-DBL_MAX;
- ymax=-DBL_MAX;
+ xmin= ymin= DBL_MAX;
+ xmax= ymax= -DBL_MAX;
}
- MBR(const double &_xmin, const double &_ymin,
- const double &_xmax, const double &_ymax)
- {
- xmin=_xmin;
- ymin=_ymin;
- xmax=_xmax;
- ymax=_ymax;
- }
+ MBR(const double xmin_arg, const double ymin_arg,
+ const double xmax_arg, const double ymax_arg)
+ :xmin(xmin_arg), ymin(ymin_arg), xmax(xmax_arg), ymax(ymax_arg)
+ {}
- MBR(const stPoint2D &min, const stPoint2D &max)
- {
- xmin=min.x;
- ymin=min.y;
- xmax=max.x;
- ymax=max.y;
- }
-
- double xmin;
- double ymin;
- double xmax;
- double ymax;
-
- void add_xy(double x, double y)
+ MBR(const st_point_2d &min, const st_point_2d &max)
+ :xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y)
+ {}
+
+ inline void add_xy(double x, double y)
{
/* Not using "else" for proper one point MBR calculation */
- if (x<xmin)
- {
- xmin=x;
- }
- if (x>xmax)
- {
- xmax=x;
- }
- if (y<ymin)
- {
- ymin=y;
- }
- if (y>ymax)
- {
- ymax=y;
- }
+ if (x < xmin)
+ xmin= x;
+ if (x > xmax)
+ xmax= x;
+ if (y < ymin)
+ ymin= y;
+ if (y > ymax)
+ ymax= y;
}
-
void add_xy(const char *px, const char *py)
{
double x, y;
float8get(x, px);
float8get(y, py);
- /* Not using "else" for proper one point MBR calculation */
- if (x<xmin)
- {
- xmin=x;
- }
- if (x>xmax)
- {
- xmax=x;
- }
- if (y<ymin)
- {
- ymin=y;
- }
- if (y>ymax)
- {
- ymax=y;
- }
+ add_xy(x,y);
}
-
void add_mbr(const MBR *mbr)
{
- if (mbr->xmin<xmin)
- {
- xmin=mbr->xmin;
- }
- if (mbr->xmax>xmax)
- {
- xmax=mbr->xmax;
- }
- if (mbr->ymin<ymin)
- {
- ymin=mbr->ymin;
- }
- if (mbr->ymax>ymax)
- {
- ymax=mbr->ymax;
- }
+ if (mbr->xmin < xmin)
+ xmin= mbr->xmin;
+ if (mbr->xmax > xmax)
+ xmax= mbr->xmax;
+ if (mbr->ymin < ymin)
+ ymin= mbr->ymin;
+ if (mbr->ymax > ymax)
+ ymax= mbr->ymax;
}
int equals(const MBR *mbr)
@@ -177,12 +139,12 @@ struct MBR
int overlaps(const MBR *mbr)
{
- int lb = mbr->inner_point(xmin, ymin);
- int rb = mbr->inner_point(xmax, ymin);
- int rt = mbr->inner_point(xmax, ymax);
- int lt = mbr->inner_point(xmin, ymax);
+ int lb= mbr->inner_point(xmin, ymin);
+ int rb= mbr->inner_point(xmax, ymin);
+ int rt= mbr->inner_point(xmax, ymax);
+ int lt= mbr->inner_point(xmin, ymax);
- int a = lb+rb+rt+lt;
+ int a = lb+rb+rt+lt;
return (a>0) && (a<4) && (!within(mbr));
}
};
@@ -190,188 +152,144 @@ struct MBR
/***************************** Geometry *******************************/
-class Geometry;
-
-typedef int (Geometry::*GF_InitFromText)(GTextReadStream *, String *);
-typedef int (Geometry::*GF_GetDataAsText)(String *) const;
-typedef size_t (Geometry::*GF_GetDataSize)() const;
-typedef int (Geometry::*GF_GetMBR)(MBR *) const;
-
-typedef int (Geometry::*GF_GetD)(double *) const;
-typedef int (Geometry::*GF_GetI)(int *) const;
-typedef int (Geometry::*GF_GetUI)(uint32 *) const;
-typedef int (Geometry::*GF_GetWS)(String *) const;
-typedef int (Geometry::*GF_GetUIWS)(uint32, String *) const;
-
-#define GEOM_METHOD_PRESENT(geom_obj, method)\
- (geom_obj.m_vmt->method != &Geometry::method)
+struct Geometry_buffer;
class Geometry
{
public:
+ static void *operator new(size_t size, void *buffer)
+ {
+ return buffer;
+ }
+
enum wkbType
{
- wkbPoint = 1,
- wkbLineString = 2,
- wkbPolygon = 3,
- wkbMultiPoint = 4,
- wkbMultiLineString = 5,
- wkbMultiPolygon = 6,
- wkbGeometryCollection = 7
+ wkb_point= 1,
+ wkb_linestring= 2,
+ wkb_polygon= 3,
+ wkb_multipoint= 4,
+ wkb_multilinestring= 5,
+ wkb_multipolygon= 6,
+ wkb_geometrycollection= 7,
+ wkb_end=7
};
enum wkbByteOrder
{
- wkbXDR = 0, /* Big Endian */
- wkbNDR = 1 /* Little Endian */
+ wkb_xdr= 0, /* Big Endian */
+ wkb_ndr= 1 /* Little Endian */
};
- class GClassInfo
+ class Class_info
{
public:
- GF_InitFromText init_from_wkt;
- GF_GetDataAsText get_data_as_wkt;
- GF_GetDataSize get_data_size;
- GF_GetMBR get_mbr;
- GF_GetD get_x;
- GF_GetD get_y;
- GF_GetD length;
- GF_GetD area;
-
- GF_GetI is_closed;
-
- GF_GetUI num_interior_ring;
- GF_GetUI num_points;
- GF_GetUI num_geometries;
- GF_GetUI dimension;
-
- GF_GetWS start_point;
- GF_GetWS end_point;
- GF_GetWS exterior_ring;
- GF_GetWS centroid;
-
- GF_GetUIWS point_n;
- GF_GetUIWS interior_ring_n;
- GF_GetUIWS geometry_n;
-
+ LEX_STRING_WITH_INIT m_name;
int m_type_id;
- const char *m_name;
- GClassInfo *m_next_rt;
+ void (*m_create_func)(void *);
+ Class_info(const char *name, int type_id, void(*create_func)(void *));
};
- GClassInfo *m_vmt;
- const GClassInfo *get_class_info() const { return m_vmt; }
- size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); }
-
- int init_from_wkt(GTextReadStream *trs, String *wkb)
- { return (this->*m_vmt->init_from_wkt)(trs, wkb); }
-
- int get_data_as_wkt(String *txt) const
- { return (this->*m_vmt->get_data_as_wkt)(txt); }
-
- int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); }
- int dimension(uint32 *dim) const
- { return (this->*m_vmt->dimension)(dim); }
-
- int get_x(double *x) const { return (this->*m_vmt->get_x)(x); }
- int get_y(double *y) const { return (this->*m_vmt->get_y)(y); }
- int length(double *len) const { return (this->*m_vmt->length)(len); }
- int area(double *ar) const { return (this->*m_vmt->area)(ar); }
-
- int is_closed(int *closed) const
- { return (this->*m_vmt->is_closed)(closed); }
-
- int num_interior_ring(uint32 *n_int_rings) const
- { return (this->*m_vmt->num_interior_ring)(n_int_rings); }
- int num_points(uint32 *n_points) const
- { return (this->*m_vmt->num_points)(n_points); }
-
- int num_geometries(uint32 *num) const
- { return (this->*m_vmt->num_geometries)(num); }
-
- int start_point(String *point) const
- { return (this->*m_vmt->start_point)(point); }
- int end_point(String *point) const
- { return (this->*m_vmt->end_point)(point); }
- int exterior_ring(String *ring) const
- { return (this->*m_vmt->exterior_ring)(ring); }
- int centroid(String *point) const
- { return (this->*m_vmt->centroid)(point); }
-
- int point_n(uint32 num, String *result) const
- { return (this->*m_vmt->point_n)(num, result); }
- int interior_ring_n(uint32 num, String *result) const
- { return (this->*m_vmt->interior_ring_n)(num, result); }
- int geometry_n(uint32 num, String *result) const
- { return (this->*m_vmt->geometry_n)(num, result); }
+ virtual const Class_info *get_class_info() const=0;
+ virtual uint32 get_data_size() const=0;
+ virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0;
+ virtual bool get_data_as_wkt(String *txt, const char **end) const=0;
+ virtual bool get_mbr(MBR *mbr, const char **end) const=0;
+ virtual bool dimension(uint32 *dim, const char **end) const=0;
+ virtual int get_x(double *x) const { return -1; }
+ virtual int get_y(double *y) const { return -1; }
+ virtual int length(double *len) const { return -1; }
+ virtual int area(double *ar, const char **end) const { return -1;}
+ virtual int is_closed(int *closed) const { return -1; }
+ virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; }
+ virtual int num_points(uint32 *n_points) const { return -1; }
+ virtual int num_geometries(uint32 *num) const { return -1; }
+ virtual int start_point(String *point) const { return -1; }
+ virtual int end_point(String *point) const { return -1; }
+ virtual int exterior_ring(String *ring) const { return -1; }
+ virtual int centroid(String *point) const { return -1; }
+ virtual int point_n(uint32 num, String *result) const { return -1; }
+ virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
+ virtual int geometry_n(uint32 num, String *result) const { return -1; }
public:
- int create_from_wkb(const char *data, uint32 data_len);
- int create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream=1);
- int init(int type_id)
- {
- m_vmt = find_class(type_id);
- return !m_vmt;
- }
- int new_geometry(const char *name, size_t len)
+ static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id)
{
- m_vmt = find_class(name, len);
- return !m_vmt;
+ Class_info *ci;
+ if (!(ci= find_class((int) type_id)))
+ return NULL;
+ (*ci->m_create_func)((void *)buffer);
+ return (Geometry *)buffer;
}
- int as_wkt(String *wkt) const
+ static Geometry *create_from_wkb(Geometry_buffer *buffer,
+ const char *data, uint32 data_len);
+ static Geometry *create_from_wkt(Geometry_buffer *buffer,
+ Gis_read_stream *trs, String *wkt,
+ bool init_stream=1);
+ int as_wkt(String *wkt, const char **end)
{
- if (wkt->reserve(strlen(get_class_info()->m_name) + 2, 512))
+ uint32 len= get_class_info()->m_name.length;
+ if (wkt->reserve(len + 2, 512))
return 1;
- wkt->qs_append(get_class_info()->m_name);
+ wkt->qs_append(get_class_info()->m_name.str, len);
wkt->qs_append('(');
- if (get_data_as_wkt(wkt))
+ if (get_data_as_wkt(wkt, end))
return 1;
wkt->qs_append(')');
return 0;
}
- void init_from_wkb(const char *data, uint32 data_len)
+ inline void init_from_wkb(const char *data, uint32 data_len)
{
- m_data = data;
- m_data_end = data + data_len;
+ m_data= data;
+ m_data_end= data + data_len;
}
- void shift_wkb_header()
+ inline void shift_wkb_header()
{
- m_data += WKB_HEADER_SIZE;
+ m_data+= WKB_HEADER_SIZE;
}
- int envelope(String *result) const;
+ bool envelope(String *result) const;
+ static Class_info *ci_collection[wkb_end+1];
protected:
- static GClassInfo *find_class(int type_id);
- static GClassInfo *find_class(const char *name, size_t len);
-
- bool no_data(const char *cur_data, uint32 data_amount) const
+ static Class_info *find_class(int type_id)
+ {
+ return ((type_id < wkb_point) || (type_id > wkb_end)) ?
+ NULL : ci_collection[type_id];
+ }
+ static Class_info *find_class(const char *name, uint32 len);
+ const char *append_points(String *txt, uint32 n_points,
+ const char *data, uint32 offset) const;
+ bool create_point(String *result, const char *data) const;
+ bool create_point(String *result, double x, double y) const;
+ const char *get_mbr_for_points(MBR *mbr, const char *data, uint offset)
+ const;
+
+ inline bool no_data(const char *cur_data, uint32 data_amount) const
{
return (cur_data + data_amount > m_data_end);
}
-
const char *m_data;
const char *m_data_end;
};
-#define SIZEOF_STORED_DOUBLE 8
/***************************** Point *******************************/
-class GPoint: public Geometry
+class Gis_point: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end) const;
+ bool get_mbr(MBR *mbr, const char **end) const;
int get_xy(double *x, double *y) const
{
- const char *data = m_data;
- if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1;
+ const char *data= m_data;
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2))
+ return 1;
float8get(*x, data);
float8get(*y, data + SIZEOF_STORED_DOUBLE);
return 0;
@@ -379,122 +297,166 @@ public:
int get_x(double *x) const
{
- if (no_data(m_data, SIZEOF_STORED_DOUBLE)) return 1;
+ if (no_data(m_data, SIZEOF_STORED_DOUBLE))
+ return 1;
float8get(*x, m_data);
return 0;
}
int get_y(double *y) const
{
- const char *data = m_data;
+ const char *data= m_data;
if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1;
float8get(*y, data + SIZEOF_STORED_DOUBLE);
return 0;
}
- int dimension(uint32 *dim) const { *dim = 0; return 0; }
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 0;
+ *end= 0; /* No default end */
+ return 0;
+ }
+ const Class_info *get_class_info() const;
};
+
/***************************** LineString *******************************/
-class GLineString: public Geometry
+class Gis_line_string: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end) const;
+ bool get_mbr(MBR *mbr, const char **end) const;
int length(double *len) const;
int is_closed(int *closed) const;
int num_points(uint32 *n_points) const;
int start_point(String *point) const;
int end_point(String *point) const;
int point_n(uint32 n, String *result) const;
- int dimension(uint32 *dim) const { *dim = 1; return 0; }
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 1;
+ *end= 0; /* No default end */
+ return 0;
+ }
+ const Class_info *get_class_info() const;
};
+
/***************************** Polygon *******************************/
-class GPolygon: public Geometry
+class Gis_polygon: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
- int area(double *ar) const;
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end) const;
+ bool get_mbr(MBR *mbr, const char **end) const;
+ int area(double *ar, const char **end) const;
int exterior_ring(String *result) const;
int num_interior_ring(uint32 *n_int_rings) const;
int interior_ring_n(uint32 num, String *result) const;
int centroid_xy(double *x, double *y) const;
int centroid(String *result) const;
- int dimension(uint32 *dim) const { *dim = 2; return 0; }
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 2;
+ *end= 0; /* No default end */
+ return 0;
+ }
+ const Class_info *get_class_info() const;
};
+
/***************************** MultiPoint *******************************/
-class GMultiPoint: public Geometry
+class Gis_multi_point: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end) const;
+ bool get_mbr(MBR *mbr, const char **end) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
- int dimension(uint32 *dim) const { *dim = 0; return 0; }
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 0;
+ *end= 0; /* No default end */
+ return 0;
+ }
+ const Class_info *get_class_info() const;
};
+
/***************************** MultiLineString *******************************/
-class GMultiLineString: public Geometry
+class Gis_multi_line_string: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end) const;
+ bool get_mbr(MBR *mbr, const char **end) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
int length(double *len) const;
int is_closed(int *closed) const;
- int dimension(uint32 *dim) const { *dim = 1; return 0; }
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 1;
+ *end= 0; /* No default end */
+ return 0;
+ }
+ const Class_info *get_class_info() const;
};
+
/***************************** MultiPolygon *******************************/
-class GMultiPolygon: public Geometry
+class Gis_multi_polygon: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end) const;
+ bool get_mbr(MBR *mbr, const char **end) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
- int area(double *ar) const;
+ int area(double *ar, const char **end) const;
int centroid(String *result) const;
- int dimension(uint32 *dim) const { *dim = 2; return 0; }
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 2;
+ *end= 0; /* No default end */
+ return 0;
+ }
+ const Class_info *get_class_info() const;
};
-/***************************** GeometryCollection *******************************/
-class GGeometryCollection: public Geometry
+/*********************** GeometryCollection *******************************/
+
+class Gis_geometry_collection: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end) const;
+ bool get_mbr(MBR *mbr, const char **end) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
- int dimension(uint32 *dim) const;
+ bool dimension(uint32 *dim, const char **end) const;
+ const Class_info *get_class_info() const;
+};
+
+const int geometry_buffer_size= sizeof(Gis_point);
+struct Geometry_buffer
+{
+ void *arr[(geometry_buffer_size - 1)/sizeof(void *) + 1];
};
#endif
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 59a96e28d77..9284b1cd574 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3170,9 +3170,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
}
- db.append (" ON `",5);
- db.append(acl_db->db);
- db.append ("`.* TO '",8);
+ db.append (" ON ",4);
+ append_identifier(thd, &db, acl_db->db, strlen(acl_db->db));
+ db.append (".* TO '",7);
db.append(lex_user->user.str,lex_user->user.length);
db.append ("'@'",3);
db.append(lex_user->host.str, lex_user->host.length);
@@ -3270,11 +3270,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
}
- global.append(" ON `",5);
- global.append(grant_table->db);
- global.append("`.`",3);
- global.append(grant_table->tname);
- global.append("` TO '",6);
+ global.append(" ON ",4);
+ append_identifier(thd, &global, grant_table->db,
+ strlen(grant_table->db));
+ global.append('.');
+ append_identifier(thd, &global, grant_table->tname,
+ strlen(grant_table->tname));
+ global.append(" TO '",5);
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_base.cc b/sql/sql_base.cc
index 37767c555e8..56857aaa632 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -46,12 +46,12 @@ extern "C" byte *table_cache_key(const byte *record,uint *length,
return (byte*) entry->table_cache_key;
}
-void table_cache_init(void)
+bool table_cache_init(void)
{
- VOID(hash_init(&open_cache,&my_charset_bin,
- table_cache_size+16,0,0,table_cache_key,
- (hash_free_key) free_cache_entry,0));
mysql_rm_tmp_tables();
+ return hash_init(&open_cache, &my_charset_bin, table_cache_size+16,
+ 0, 0,table_cache_key,
+ (hash_free_key) free_cache_entry, 0) != 0;
}
void table_cache_free(void)
@@ -520,6 +520,16 @@ void close_temporary_tables(THD *thd)
/* The -1 is to remove last ',' */
thd->clear_error();
Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0);
+ /*
+ Imagine the thread had created a temp table, then was doing a SELECT, and
+ the SELECT was killed. Then it's not clever to mark the statement above as
+ "killed", because it's not really a statement updating data, and there
+ are 99.99% chances it will succeed on slave.
+ If a real update (one updating a persistent table) was killed on the
+ master, then this real update will be logged with error_code=killed,
+ rightfully causing the slave to stop.
+ */
+ qinfo.error_code= 0;
mysql_bin_log.write(&qinfo);
}
thd->temporary_tables=0;
@@ -1417,10 +1427,10 @@ int open_tables(THD *thd, TABLE_LIST *start, uint *counter)
bool refresh;
int result=0;
DBUG_ENTER("open_tables");
- *counter= 0;
thd->current_tablenr= 0;
restart:
+ *counter= 0;
thd->proc_info="Opening tables";
for (tables=start ; tables ; tables=tables->next)
{
@@ -1762,7 +1772,11 @@ bool rm_temporary_table(enum db_type base, char *path)
*fn_ext(path)='\0'; // remove extension
handler *file=get_new_handler((TABLE*) 0, base);
if (file && file->delete_table(path))
+ {
error=1;
+ sql_print_error("Warning: Could not remove tmp table: '%s', error: %d",
+ path, my_errno);
+ }
delete file;
DBUG_RETURN(error);
}
@@ -2140,10 +2154,9 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
Item **ref= ref_pointer_array;
while ((item= it++))
{
- if (item->fix_fields(thd, tables, it.ref()) ||
- item->check_cols(1))
+ if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
+ (item= *(it.ref()))->check_cols(1))
DBUG_RETURN(-1); /* purecov: inspected */
- item= *(it.ref()); //Item can be changed in fix fields
if (ref)
*(ref++)= item;
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
@@ -2323,7 +2336,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
if (*conds)
{
thd->where="where clause";
- if ((*conds)->fix_fields(thd, tables, conds) || (*conds)->check_cols(1))
+ if (!(*conds)->fixed && (*conds)->fix_fields(thd, tables, conds) ||
+ (*conds)->check_cols(1))
DBUG_RETURN(1);
not_null_tables= (*conds)->not_null_tables();
}
@@ -2335,7 +2349,9 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
/* Make a join an a expression */
thd->where="on clause";
- if (table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
+
+ if (!table->on_expr->fixed &&
+ table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
table->on_expr->check_cols(1))
DBUG_RETURN(1);
thd->lex->current_select->cond_count++;
@@ -2349,7 +2365,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
!(specialflag & SPECIAL_NO_NEW_FUNC)))
{
table->outer_join= 0;
- if (!(*conds=and_conds(*conds, table->on_expr)))
+ if (!(*conds= and_conds(*conds, table->on_expr, tables)))
DBUG_RETURN(1);
table->on_expr=0;
}
@@ -2357,9 +2373,9 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
if (table->natural_join)
{
/* Make a join of all fields with have the same name */
- TABLE *t1=table->table;
- TABLE *t2=table->natural_join->table;
- Item_cond_and *cond_and=new Item_cond_and();
+ TABLE *t1= table->table;
+ TABLE *t2= table->natural_join->table;
+ Item_cond_and *cond_and= new Item_cond_and();
if (!cond_and) // If not out of memory
DBUG_RETURN(1);
cond_and->top_level_item();
@@ -2374,12 +2390,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
t1->field[i]->field_name,
t2->field[j]->field_name))
{
- Item_func_eq *tmp=new Item_func_eq(new Item_field(t1->field[i]),
- new Item_field(t2->field[j]));
+ Item_func_eq *tmp= new Item_func_eq(new Item_field(t1->field[i]),
+ new Item_field(t2->field[j]));
if (!tmp)
DBUG_RETURN(1);
- tmp->fix_length_and_dec(); // Update cmp_type
- tmp->const_item_cache=0;
/* Mark field used for table cache */
t1->field[i]->query_id=t2->field[j]->query_id=thd->query_id;
cond_and->list.push_back(tmp);
@@ -2389,15 +2403,22 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
}
}
- cond_and->used_tables_cache= t1->map | t2->map;
thd->lex->current_select->cond_count+= cond_and->list.elements;
+
if (!table->outer_join) // Not left join
{
- if (!(*conds=and_conds(*conds, cond_and)))
+ if (!(*conds= and_conds(*conds, cond_and, tables)) ||
+ (*conds && !(*conds)->fixed &&
+ (*conds)->fix_fields(thd, tables, conds)))
DBUG_RETURN(1);
}
else
- table->on_expr=and_conds(table->on_expr,cond_and);
+ {
+ table->on_expr= and_conds(table->on_expr, cond_and, tables);
+ if (table->on_expr && !table->on_expr->fixed &&
+ table->on_expr->fix_fields(thd, tables, &table->on_expr))
+ DBUG_RETURN(1);
+ }
}
}
DBUG_RETURN(test(thd->net.report_error));
@@ -2424,7 +2445,7 @@ fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors)
TABLE *table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= true;
- if (value->save_in_field(rfield, 0) > 0 && !ignore_errors)
+ if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -2445,7 +2466,7 @@ fill_record(Field **ptr,List<Item> &values, bool ignore_errors)
TABLE *table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= true;
- if (value->save_in_field(field, 0) == 1 && !ignore_errors)
+ if ((value->save_in_field(field, 0) < 0) && !ignore_errors)
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -2596,7 +2617,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
if (table->db_stat)
result=1;
/* Kill delayed insert threads */
- if (in_use->system_thread && ! in_use->killed)
+ if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) &&
+ ! in_use->killed)
{
in_use->killed=1;
pthread_mutex_lock(&in_use->mysys_var->mutex);
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 7c31281c926..40d9b1b42d8 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1158,6 +1158,37 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
DBUG_VOID_RETURN;
}
+
+/*
+ Invalidate locked for write
+
+ SYNOPSIS
+ Query_cache::invalidate_locked_for_write()
+ tables_used - table list
+
+ NOTE
+ can be used only for opened tables
+*/
+void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
+{
+ DBUG_ENTER("Query_cache::invalidate (changed table list)");
+ if (query_cache_size > 0 && tables_used)
+ {
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (query_cache_size > 0)
+ {
+ DUMP(this);
+ for (; tables_used; tables_used= tables_used->next)
+ {
+ if (tables_used->lock_type & (TL_WRITE_LOW_PRIORITY | TL_WRITE))
+ invalidate_table(tables_used->table);
+ }
+ }
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ }
+ DBUG_VOID_RETURN;
+}
+
/*
Remove all cached queries that uses the given table
*/
@@ -2562,20 +2593,15 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
tables_used->db, tables_used->table->db_type));
*tables_type|= tables_used->table->file->table_cache_type();
+ /*
+ table_alias_charset used here because it depends of
+ lower_case_table_names variable
+ */
if (tables_used->table->db_type == DB_TYPE_MRG_ISAM ||
tables_used->table->tmp_table != NO_TMP_TABLE ||
(tables_used->db_length == 5 &&
-#ifdef FN_NO_CASE_SENCE
- my_strnncoll(system_charset_info, (uchar*)tables_used->db, 6,
- (uchar*)"mysql",6) == 0
-#else
- tables_used->db[0]=='m' &&
- tables_used->db[1]=='y' &&
- tables_used->db[2]=='s' &&
- tables_used->db[3]=='q' &&
- tables_used->db[4]=='l'
-#endif
- ))
+ my_strnncoll(table_alias_charset, (uchar*)tables_used->db, 6,
+ (uchar*)"mysql",6) == 0))
{
DBUG_PRINT("qcache",
("select not cacheable: used MRG_ISAM, temporary or system table(s)"));
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index ac4f465bf79..432c7659aa5 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -375,6 +375,7 @@ protected:
void invalidate(THD* thd, TABLE_LIST *tables_used,
my_bool using_transactions);
void invalidate(CHANGED_TABLE_LIST *tables_used);
+ void invalidate_locked_for_write(TABLE_LIST *tables_used);
void invalidate(THD* thd, TABLE *table, my_bool using_transactions);
void invalidate(THD *thd, const char *key, uint32 key_length,
my_bool using_transactions);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 6fe0521b07a..945414f532b 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -145,8 +145,7 @@ THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
init();
/* Initialize sub structures */
- bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
- bzero((char*) &warn_root,sizeof(warn_root));
+ clear_alloc_root(&transaction.mem_root);
init_alloc_root(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
user_connect=(USER_CONN *)0;
hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0,
@@ -331,7 +330,7 @@ THD::~THD()
dbug_sentry = THD_SENTRY_GONE;
#endif
/* Reset stmt_backup.mem_root to not double-free memory from thd.mem_root */
- init_alloc_root(&stmt_backup.mem_root, 0, 0);
+ clear_alloc_root(&stmt_backup.mem_root);
DBUG_VOID_RETURN;
}
@@ -1170,8 +1169,12 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
ls= gl++;
Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item);
+ /*
+ Item_func_set_user_var can't substitute something else on its place =>
+ 0 can be passed as last argument (reference on item)
+ */
xx->fix_fields(thd,(TABLE_LIST*) thd->lex->select_lex.table_list.first,
- &item);
+ 0);
xx->fix_length_and_dec();
vars.push_back(xx);
}
@@ -1185,10 +1188,8 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
Statement::Statement(THD *thd)
:id(++thd->statement_id_counter),
- query_id(thd->query_id),
set_query_id(1),
allow_sum_func(0),
- command(thd->command),
lex(&main_lex),
query(0),
query_length(0),
@@ -1207,10 +1208,8 @@ Statement::Statement(THD *thd)
Statement::Statement()
:id(0),
- query_id(0), /* initialized later */
set_query_id(1),
allow_sum_func(0), /* initialized later */
- command(COM_SLEEP), /* initialized later */
lex(&main_lex),
query(0), /* these two are set */
query_length(0), /* in alloc_query() */
@@ -1229,15 +1228,11 @@ Statement::Type Statement::type() const
void Statement::set_statement(Statement *stmt)
{
id= stmt->id;
- query_id= stmt->query_id;
set_query_id= stmt->set_query_id;
allow_sum_func= stmt->allow_sum_func;
- command= stmt->command;
lex= stmt->lex;
query= stmt->query;
query_length= stmt->query_length;
- free_list= stmt->free_list;
- mem_root= stmt->mem_root;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index d0ad8a4e681..51039999345 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -194,6 +194,7 @@ public:
typedef struct st_copy_info {
ha_rows records;
ha_rows deleted;
+ ha_rows updated;
ha_rows copied;
ha_rows error_count;
enum enum_duplicates handle_duplicates;
@@ -351,6 +352,7 @@ struct system_variables
ulong max_length_for_sort_data;
ulong max_sort_length;
ulong max_tmp_tables;
+ ulong max_insert_delayed_threads;
ulong myisam_repair_threads;
ulong myisam_sort_buff_size;
ulong net_buffer_length;
@@ -386,6 +388,7 @@ struct system_variables
my_bool log_warnings;
my_bool low_priority_updates;
my_bool new_mode;
+ my_bool query_cache_wlock_invalidate;
my_bool old_passwords;
/* Only charset part of these variables is sensible */
@@ -435,15 +438,6 @@ public:
ulong id;
/*
- Id of current query. Statement can be reused to execute several queries
- query_id is global in context of the whole MySQL server.
- ID is automatically generated from mutex-protected counter.
- It's used in handler code for various purposes: to check which columns
- from table are necessary for this select, to check if it's necessary to
- update auto-updatable fields (like auto_increment and timestamp).
- */
- ulong query_id;
- /*
- if set_query_id=1, we set field->query_id for all fields. In that case
field list can not contain duplicates.
*/
@@ -461,11 +455,6 @@ public:
See item_sum.cc for details.
*/
bool allow_sum_func;
- /*
- Type of current query: COM_PREPARE, COM_QUERY, etc. Set from
- first byte of the packet in do_command()
- */
- enum enum_server_command command;
LEX *lex; // parse tree descriptor
/*
@@ -671,11 +660,16 @@ public:
points to a lock object if the lock is present. See item_func.cc and
chapter 'Miscellaneous functions', for functions GET_LOCK, RELEASE_LOCK.
*/
- ULL *ull;
+ User_level_lock *ull;
#ifndef DBUG_OFF
uint dbug_sentry; // watch out for memory corruption
#endif
struct st_my_thread_var *mysys_var;
+ /*
+ Type of current query: COM_PREPARE, COM_QUERY, etc. Set from
+ first byte of the packet in do_command()
+ */
+ enum enum_server_command command;
uint32 server_id;
uint32 file_id; // for LOAD DATA INFILE
/*
@@ -751,6 +745,15 @@ public:
List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count;
+ /*
+ Id of current query. Statement can be reused to execute several queries
+ query_id is global in context of the whole MySQL server.
+ ID is automatically generated from mutex-protected counter.
+ It's used in handler code for various purposes: to check which columns
+ from table are necessary for this select, to check if it's necessary to
+ update auto-updatable fields (like auto_increment and timestamp).
+ */
+ ulong query_id;
ulong warn_id, version, options, thread_id, col_access;
/* Statement id is thread-wide. This counter is used to generate ids */
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 7bf1268597b..08582391754 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -465,6 +465,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
idx++)
{
FILEINFO *file=dirp->dir_entry+idx;
+ char *extension;
DBUG_PRINT("info",("Examining: %s", file->name));
/* Check if file is a raid directory */
@@ -474,81 +475,73 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
(file->name[1] >= 'a' && file->name[1] <= 'f')) &&
!file->name[2] && !level)
{
- char newpath[FN_REFLEN];
+ char newpath[FN_REFLEN], *copy_of_path;
MY_DIR *new_dirp;
String *dir;
+ uint length;
strxmov(newpath,org_path,"/",file->name,NullS);
- unpack_filename(newpath,newpath);
+ length= unpack_filename(newpath,newpath);
if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
{
DBUG_PRINT("my",("New subdir found: %s", newpath));
if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1)) < 0)
- {
- my_dirend(dirp);
- DBUG_RETURN(-1);
- }
- raid_dirs.push_back(dir=new String(newpath, &my_charset_latin1));
- dir->copy();
+ goto err;
+ if (!(copy_of_path= thd->memdup(newpath, length+1)) ||
+ !(dir= new (&thd->mem_root) String(copy_of_path, length,
+ &my_charset_bin)) ||
+ raid_dirs.push_back(dir))
+ goto err;
continue;
}
found_other_files++;
continue;
}
- if (find_type(fn_ext(file->name),&deletable_extentions,1+2) <= 0)
+ extension= fn_ext(file->name);
+ if (find_type(extension, &deletable_extentions,1+2) <= 0)
{
- if (find_type(fn_ext(file->name),&known_extentions,1+2) <= 0)
+ if (find_type(extension, &known_extentions,1+2) <= 0)
found_other_files++;
continue;
}
- strxmov(filePath,org_path,"/",file->name,NullS);
- if (db && !my_strcasecmp(&my_charset_latin1,
- fn_ext(file->name), reg_ext))
+ // just for safety we use files_charset_info
+ if (db && !my_strcasecmp(files_charset_info,
+ extension, reg_ext))
{
/* Drop the table nicely */
- *fn_ext(file->name)=0; // Remove extension
+ *extension= 0; // Remove extension
TABLE_LIST *table_list=(TABLE_LIST*)
thd->calloc(sizeof(*table_list)+ strlen(db)+strlen(file->name)+2);
if (!table_list)
- {
- my_dirend(dirp);
- DBUG_RETURN(-1);
- }
+ goto err;
table_list->db= (char*) (table_list+1);
- strmov(table_list->real_name=strmov(table_list->db,db)+1,
- file->name);
+ strmov(table_list->real_name= strmov(table_list->db,db)+1, file->name);
+ table_list->alias= table_list->real_name; // If lower_case_table_names=2
/* Link into list */
(*tot_list_next)= table_list;
tot_list_next= &table_list->next;
+ deleted++;
}
else
{
-
+ strxmov(filePath, org_path, "/", file->name, NullS);
if (my_delete_with_symlink(filePath,MYF(MY_WME)))
{
- my_dirend(dirp);
- DBUG_RETURN(-1);
+ goto err;
}
- deleted++;
}
}
- List_iterator<String> it(raid_dirs);
- String *dir;
-
if (thd->killed ||
(tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1)))
+ goto err;
+
+ /* Remove RAID directories */
{
- /* Free memory for allocated raid dirs */
+ List_iterator<String> it(raid_dirs);
+ String *dir;
while ((dir= it++))
- delete dir;
- my_dirend(dirp);
- DBUG_RETURN(-1);
- }
- while ((dir= it++))
- {
- if (rmdir(dir->c_ptr()) < 0)
- found_other_files++;
- delete dir;
+ if (rmdir(dir->c_ptr()) < 0)
+ found_other_files++;
}
my_dirend(dirp);
@@ -559,7 +552,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
if (!found_other_files)
{
char tmp_path[FN_REFLEN], *pos;
- char *path=unpack_filename(tmp_path,org_path);
+ char *path= tmp_path;
+ unpack_filename(tmp_path,org_path);
#ifdef HAVE_READLINK
int error;
@@ -596,6 +590,10 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
}
}
DBUG_RETURN(deleted);
+
+err:
+ my_dirend(dirp);
+ DBUG_RETURN(-1);
}
@@ -626,13 +624,13 @@ bool mysql_change_db(THD *thd, const char *name)
HA_CREATE_INFO create;
DBUG_ENTER("mysql_change_db");
- if (!dbname || !(db_length=strip_sp(dbname)))
+ if (!dbname || !(db_length= strlen(dbname)))
{
x_free(dbname); /* purecov: inspected */
send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
- if ((db_length > NAME_LEN) || check_db_name(dbname))
+ if (check_db_name(dbname))
{
net_printf(thd, ER_WRONG_DB_NAME, dbname);
x_free(dbname);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index fe7d881a863..a2f2c4abae4 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -187,6 +187,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
else
table->file->unlock_row(); // Row failed selection, release lock on it
}
+ if (thd->killed && !error)
+ error= 1; // Aborted
thd->proc_info="end";
end_read_record(&info);
free_io_cache(table); // Will not do any harm
@@ -389,6 +391,7 @@ bool multi_delete::send_data(List<Item> &values)
DBUG_RETURN(0);
}
+
void multi_delete::send_error(uint errcode,const char *err)
{
DBUG_ENTER("multi_delete::send_error");
@@ -473,15 +476,13 @@ int multi_delete::do_deletes(bool from_send_error)
if ((local_error=table->file->delete_row(table->record[0])))
{
table->file->print_error(local_error,MYF(0));
- if (transactional_tables)
- {
- DBUG_RETURN(local_error);
- }
break;
}
deleted++;
}
end_read_record(&info);
+ if (thd->killed && !local_error)
+ local_error= 1;
if (local_error == -1) // End of file
local_error = 0;
}
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 0e04316a2e7..4bfb8cdfe3c 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -151,7 +151,11 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
if (is_union)
- res= mysql_union(thd, lex, derived_result, unit);
+ {
+ // execute union without clean up
+ if (!(res= unit->prepare(thd, derived_result, SELECT_NO_UNLOCK)))
+ res= unit->exec();
+ }
else
{
unit->offset_limit_cnt= first_select->offset_limit;
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index d0f241b3291..1579ac3b5c8 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -35,7 +35,7 @@
But !!! do_command calls free_root at the end of every query and frees up
all the sql_alloc'ed memory. It's harder to work around...
- */
+*/
#define HANDLER_TABLES_HACK(thd) { \
TABLE *tmp=thd->open_tables; \
@@ -207,11 +207,13 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
MYF(0),keyinfo->key_parts);
goto err;
}
- List_iterator_fast<Item> it_ke(*key_expr);
+ List_iterator<Item> it_ke(*key_expr);
Item *item;
for (key_len=0 ; (item=it_ke++) ; key_part++)
{
- if (item->fix_fields(thd, tables, &item))
+ // 'item' can be changed by fix_fields() call
+ if (item->fix_fields(thd, tables, it_ke.ref()) ||
+ (item= *it_ke.ref())->check_cols(1))
goto err;
if (item->used_tables() & ~RAND_TABLE_BIT)
{
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index d5516fe3337..f6bae67c3b6 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -140,7 +140,7 @@ void memorize_variant_topic(THD *thd, TABLE *topics, int count,
{
if (count == 1)
names->push_back(name);
- String *new_name= new String;
+ String *new_name= new (&thd->mem_root) String;
get_field(mem_root,find_fields[help_topic_name].field,new_name);
names->push_back(new_name);
}
@@ -391,7 +391,7 @@ int search_categories(THD *thd, TABLE *categories,
{
if (select && !select->cond->val_int())
continue;
- String *lname= new String;
+ String *lname= new (&thd->mem_root) String;
get_field(&thd->mem_root,pfname,lname);
if (++count == 1 && res_id)
*res_id= (int16) pcat_id->val_int();
@@ -425,7 +425,7 @@ void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname,
{
if (!select->cond->val_int())
continue;
- String *name= new String();
+ String *name= new (&thd->mem_root) String();
get_field(&thd->mem_root,pfname,name);
res->push_back(name);
}
@@ -743,15 +743,18 @@ int mysqld_help(THD *thd, const char *mask)
else
{
Field *topic_cat_id= used_fields[help_topic_help_category_id].field;
- Item *cond_topic_by_cat= new Item_func_equal(new Item_field(topic_cat_id),
- new Item_int((int32)category_id));
- Item *cond_cat_by_cat= new Item_func_equal(new Item_field(cat_cat_id),
- new Item_int((int32)category_id));
+ Item *cond_topic_by_cat=
+ new Item_func_equal(new Item_field(topic_cat_id),
+ new Item_int((int32)category_id));
+ Item *cond_cat_by_cat=
+ new Item_func_equal(new Item_field(cat_cat_id),
+ new Item_int((int32)category_id));
if (!(select_topics_by_cat= prepare_simple_select(thd,cond_topic_by_cat,
tables,tables[0].table,
&error)) ||
- !(select_cat_by_cat= prepare_simple_select(thd,cond_cat_by_cat,tables,
- tables[1].table,&error)))
+ !(select_cat_by_cat=
+ prepare_simple_select(thd,cond_cat_by_cat,tables,
+ tables[1].table,&error)))
{
res= -1;
goto end;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index ccb8296b929..a9b947505f0 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -150,7 +150,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
*/
if ((lock_type == TL_WRITE_DELAYED &&
((specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) ||
- thd->slave_thread || !max_insert_delayed_threads)) ||
+ thd->slave_thread || !thd->variables.max_insert_delayed_threads)) ||
(lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE) ||
(duplic == DUP_UPDATE))
lock_type=TL_WRITE;
@@ -236,7 +236,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
Fill in the given fields and dump it to the table file
*/
- info.records=info.deleted=info.copied=0;
+ info.records= info.deleted= info.copied= info.updated= 0;
info.handle_duplicates=duplic;
info.update_fields=&update_fields;
info.update_values=&update_values;
@@ -369,13 +369,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
For the transactional algorithm to work the invalidation must be
before binlog writing and ha_autocommit_...
*/
- if (info.copied || info.deleted)
+ if (info.copied || info.deleted || info.updated)
query_cache_invalidate3(thd, table_list, 1);
transactional_table= table->file->has_transactions();
log_delayed= (transactional_table || table->tmp_table);
- if ((info.copied || info.deleted) && (error <= 0 || !transactional_table))
+ if ((info.copied || info.deleted || info.updated) &&
+ (error <= 0 || !transactional_table))
{
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
@@ -416,7 +417,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
goto abort;
if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) ||
!thd->cuted_fields))
- send_ok(thd,info.copied+info.deleted,id);
+ send_ok(thd,info.copied+info.deleted+info.updated,id);
else
{
char buff[160];
@@ -426,8 +427,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
- (ulong) info.deleted, (ulong) thd->cuted_fields);
- ::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff);
+ (ulong) info.deleted+info.updated, (ulong) thd->cuted_fields);
+ ::send_ok(thd,info.copied+info.deleted+info.updated,(ulonglong)id,buff);
}
free_underlaid_joins(thd, &thd->lex->select_lex);
table->insert_values=0;
@@ -529,7 +530,7 @@ int write_record(TABLE *table,COPY_INFO *info)
goto err;
if ((error=table->file->update_row(table->record[1],table->record[0])))
goto err;
- info->deleted++;
+ info->updated++;
break;
}
else /* DUP_REPLACE */
@@ -749,7 +750,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
if (!(tmp=find_handler(thd,table_list)))
{
/* Don't create more than max_insert_delayed_threads */
- if (delayed_insert_threads >= max_insert_delayed_threads)
+ if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads)
DBUG_RETURN(0);
thd->proc_info="Creating delayed handler";
pthread_mutex_lock(&LOCK_delayed_create);
@@ -1330,8 +1331,15 @@ bool delayed_insert::handle_inserts(void)
pthread_mutex_lock(&mutex);
delete row;
- /* Let READ clients do something once in a while */
- if (group_count++ == max_rows)
+ /*
+ Let READ clients do something once in a while
+ We should however not break in the middle of a multi-line insert
+ if we have binary logging enabled as we don't want other commands
+ on this table until all entries has been processed
+ */
+ if (group_count++ >= max_rows && (row= rows.head()) &&
+ (!(row->log_query & DELAYED_LOG_BIN && using_bin_log) ||
+ row->query))
{
group_count=0;
if (stacked_inserts || tables_in_use) // Let these wait a while
@@ -1474,7 +1482,8 @@ void select_insert::send_error(uint errcode,const char *err)
error while inserting into a MyISAM table) we must write to the binlog (and
the error code will make the slave stop).
*/
- if ((info.copied || info.deleted) && !table->file->has_transactions())
+ if ((info.copied || info.deleted || info.updated) &&
+ !table->file->has_transactions())
{
if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log
@@ -1488,7 +1497,7 @@ void select_insert::send_error(uint errcode,const char *err)
if (!table->tmp_table)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (info.copied || info.deleted)
+ if (info.copied || info.deleted || info.updated)
query_cache_invalidate3(thd, table, 1);
ha_rollback_stmt(thd);
DBUG_VOID_RETURN;
@@ -1509,7 +1518,7 @@ bool select_insert::send_eof()
and ha_autocommit_...
*/
- if (info.copied || info.deleted)
+ if (info.copied || info.deleted || info.updated)
{
query_cache_invalidate3(thd, table, 1);
if (!(table->file->has_transactions() || table->tmp_table))
@@ -1543,8 +1552,8 @@ bool select_insert::send_eof()
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
- (ulong) info.deleted, (ulong) thd->cuted_fields);
- ::send_ok(thd,info.copied+info.deleted,last_insert_id,buff);
+ (ulong) info.deleted+info.updated, (ulong) thd->cuted_fields);
+ ::send_ok(thd,info.copied+info.deleted+info.updated,last_insert_id,buff);
DBUG_RETURN(0);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index ce7aa4d02db..757eb4fdc7d 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1321,8 +1321,8 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
DESCRIPTION
This is used for UNION & subselect to create a new table list of all used
tables.
- The table_list->table entry in all used tables are set to point
- to the entries in this list.
+ The table_list->table_list in all tables of global list are set to point
+ to the local SELECT_LEX entries.
RETURN
0 - OK
@@ -1373,7 +1373,7 @@ create_total_list_n_last_return(THD *thd_arg,
{
TABLE_LIST *cursor;
next_table= aux->next;
- /* Add not used table to the total table list */
+ /* Add to the total table list */
if (!(cursor= (TABLE_LIST *) thd->memdup((char*) aux,
sizeof(*aux))))
{
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 17cccd75697..ba8fe0d8792 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -552,7 +552,7 @@ typedef struct st_lex
List<Item> *insert_list,field_list,value_list;
List<List_item> many_values;
List<set_var_base> var_list;
- List<Item> param_list;
+ List<Item_param> param_list;
SQL_LIST proc_list, auxilliary_table_list, save_list;
TYPELIB *interval;
create_field *last_field;
@@ -577,7 +577,6 @@ typedef struct st_lex
uint uint_geom_type;
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
- uint param_count;
uint slave_thd_opt;
uint8 describe;
bool drop_if_exists, drop_temporary, local_file;
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 0bbc0f87944..22e9ed37386 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -357,6 +357,10 @@ class base_ilist
first_link->unlink(); // Unlink from list
return first_link;
}
+ inline struct ilink *head()
+ {
+ return (first != &last) ? first : 0;
+ }
friend class base_list_iterator;
};
@@ -389,6 +393,7 @@ public:
inline void append(T* a) { base_ilist::append(a); }
inline void push_back(T* a) { base_ilist::push_back(a); }
inline T* get() { return (T*) base_ilist::get(); }
+ inline T* head() { return (T*) base_ilist::head(); }
#ifndef _lint
friend class I_List_iterator<T>;
#endif
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a09f3d28a0f..73811dddf75 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -101,6 +101,7 @@ static void unlock_locked_tables(THD *thd)
}
}
+
static bool end_active_trans(THD *thd)
{
int error=0;
@@ -116,6 +117,17 @@ static bool end_active_trans(THD *thd)
}
+#ifdef HAVE_REPLICATION
+inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
+{
+ return (table_rules_on && tables && !tables_ok(thd,tables) &&
+ ((thd->lex->sql_command != SQLCOM_DELETE_MULTI) ||
+ !tables_ok(thd,
+ (TABLE_LIST *)thd->lex->auxilliary_table_list.first)));
+}
+#endif
+
+
static HASH hash_user_connections;
static int get_or_create_user_conn(THD *thd, const char *user,
@@ -988,7 +1000,7 @@ pthread_handler_decl(handle_one_connection,arg)
net->compress=1; // Use compression
thd->version= refresh_version;
- if (sys_init_connect.value && !(thd->master_access & SUPER_ACL))
+ if (sys_init_connect.value_length && !(thd->master_access & SUPER_ACL))
{
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
if (thd->query_error)
@@ -1180,9 +1192,18 @@ err:
}
- /* Execute one command from socket (query or simple command) */
-
#ifndef EMBEDDED_LIBRARY
+
+/*
+ Read one command from socket and execute it (query or simple command).
+ This function is called in loop from thread function.
+ SYNOPSIS
+ do_command()
+ RETURN VALUE
+ 0 success
+ 1 request of thread shutdown (see dispatch_command() description)
+*/
+
bool do_command(THD *thd)
{
char *packet;
@@ -1232,10 +1253,34 @@ bool do_command(THD *thd)
command_name[command]));
}
net->read_timeout=old_timeout; // restore it
+ /*
+ packet_length contains length of data, as it was stored in packet
+ header. In case of malformed header, packet_length can be zero.
+ If packet_length is not zero, my_net_read ensures that this number
+ of bytes was actually read from network. Additionally my_net_read
+ sets packet[packet_length]= 0 (thus if packet_length == 0,
+ command == packet[0] == COM_SLEEP).
+ In dispatch_command packet[packet_length] points beyond the end of packet.
+ */
DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
}
#endif /* EMBEDDED_LIBRARY */
+/*
+ Perform one connection-level (COM_XXXX) command.
+ SYNOPSIS
+ dispatch_command()
+ thd connection handle
+ command type of command to perform
+ packet data for the command, packet is always null-terminated
+ packet_length length of packet + 1 (to show that data is
+ null-terminated) except for COM_SLEEP, where it
+ can be zero.
+ RETURN VALUE
+ 0 ok
+ 1 request of thread shutdown, i. e. if command is
+ COM_QUIT/COM_SHUTDOWN
+*/
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length)
@@ -1372,7 +1417,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_EXECUTE:
{
- mysql_stmt_execute(thd, packet);
+ mysql_stmt_execute(thd, packet, packet_length);
break;
}
case COM_LONG_DATA:
@@ -1504,8 +1549,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
// null test to handle EOM
- if (!db || !strip_sp(db) || !(alias= thd->strdup(db)) ||
- check_db_name(db))
+ if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
{
net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
@@ -1521,8 +1565,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
char *db=thd->strdup(packet), *alias;
// null test to handle EOM
- if (!db || !strip_sp(db) || !(alias= thd->strdup(db)) ||
- check_db_name(db))
+ if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
{
net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
@@ -1800,9 +1843,7 @@ mysql_execute_command(THD *thd)
Skip if we are in the slave thread, some table rules have been
given and the table list says the query should not be replicated
*/
- if (table_rules_on && tables && !tables_ok(thd,tables) &&
- ((lex->sql_command != SQLCOM_DELETE_MULTI) ||
- !tables_ok(thd,(TABLE_LIST *)thd->lex->auxilliary_table_list.first)))
+ if (all_tables_not_ok(thd,tables))
{
/* we warn the slave SQL thread */
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
@@ -2042,9 +2083,9 @@ mysql_execute_command(THD *thd)
{
if (check_global_access(thd, SUPER_ACL))
goto error;
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
res = change_master(thd,active_mi);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
break;
}
case SQLCOM_SHOW_SLAVE_STAT:
@@ -2052,9 +2093,9 @@ mysql_execute_command(THD *thd)
/* Accept one of two privileges */
if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
res = show_master_info(thd,active_mi);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
break;
}
case SQLCOM_SHOW_MASTER_STAT:
@@ -2106,7 +2147,7 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_WRONG_TABLE_NAME, tables->real_name);
break;
}
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
/*
fetch_master_table will send the error to the client on failure.
Give error if the table already exists.
@@ -2116,7 +2157,7 @@ mysql_execute_command(THD *thd)
{
send_ok(thd);
}
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
break;
}
#endif /* HAVE_REPLICATION */
@@ -2232,9 +2273,9 @@ mysql_execute_command(THD *thd)
#ifdef HAVE_REPLICATION
case SQLCOM_SLAVE_START:
{
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
start_slave(thd,active_mi,1 /* net report*/);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
break;
}
case SQLCOM_SLAVE_STOP:
@@ -2257,9 +2298,9 @@ mysql_execute_command(THD *thd)
break;
}
{
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
stop_slave(thd,active_mi,1/* net report*/);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
break;
}
#endif /* HAVE_REPLICATION */
@@ -2670,7 +2711,7 @@ mysql_execute_command(THD *thd)
TABLE_LIST *walk;
for (walk= (TABLE_LIST*) tables; walk; walk= walk->next)
{
- if (!strcmp(auxi->real_name, walk->alias) &&
+ if (!my_strcasecmp(table_alias_charset, auxi->alias, walk->alias) &&
!strcmp(walk->db, auxi->db))
break;
}
@@ -2970,8 +3011,12 @@ mysql_execute_command(THD *thd)
goto error;
thd->in_lock_tables=1;
thd->options|= OPTION_TABLE_LOCK;
- if (!(res=open_and_lock_tables(thd,tables)))
+ if (!(res= open_and_lock_tables(thd, tables)))
{
+#ifdef HAVE_QUERY_CACHE
+ if (thd->variables.query_cache_wlock_invalidate)
+ query_cache.invalidate_locked_for_write(tables);
+#endif /*HAVE_QUERY_CACHE*/
thd->locked_tables=thd->lock;
thd->lock=0;
send_ok(thd);
@@ -2983,8 +3028,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_CREATE_DB:
{
char *alias;
- if (!strip_sp(lex->name) || !(alias=thd->strdup(lex->name)) ||
- check_db_name(lex->name))
+ if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name))
{
net_printf(thd,ER_WRONG_DB_NAME, lex->name);
break;
@@ -3014,8 +3058,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_DROP_DB:
{
char *alias;
- if (!strip_sp(lex->name) || !(alias=thd->strdup(lex->name)) ||
- check_db_name(lex->name))
+ if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name))
{
net_printf(thd, ER_WRONG_DB_NAME, lex->name);
break;
@@ -3875,8 +3918,11 @@ void mysql_init_multi_delete(LEX *lex)
}
-void
-mysql_parse(THD *thd, char *inBuf, uint length)
+/*
+ When you modify mysql_parse(), you may need to mofify
+ mysql_test_parse_for_slave() in this same file.
+*/
+void mysql_parse(THD *thd, char *inBuf, uint length)
{
DBUG_ENTER("mysql_parse");
@@ -3918,6 +3964,33 @@ mysql_parse(THD *thd, char *inBuf, uint length)
}
+#ifdef HAVE_REPLICATION
+/*
+ Usable by the replication SQL thread only: just parse a query to know if it
+ can be ignored because of replicate-*-table rules.
+
+ RETURN VALUES
+ 0 cannot be ignored
+ 1 can be ignored
+*/
+
+bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
+{
+ LEX *lex;
+ bool error= 0;
+
+ mysql_init_query(thd);
+ lex= lex_start(thd, (uchar*) inBuf, length);
+ if (!yyparse((void*) thd) && ! thd->is_fatal_error &&
+ all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
+ error= 1; /* Ignore question */
+ free_items(thd->free_list); /* Free strings used by items */
+ lex_end(lex);
+
+ return error;
+}
+#endif
+
/*****************************************************************************
** Store field definition for create
** Return 0 if ok
@@ -3959,6 +4032,9 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if (default_value)
{
/*
+ Default value should be literal => basic constants =>
+ no need fix_fields()
+
We allow specifying value for first TIMESTAMP column
altough it is silently ignored. This should be fixed in 4.1
(by proper warning or real support for default values)
@@ -4419,7 +4495,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
tables ;
tables=tables->next)
{
- if (!strcmp(alias_str,tables->alias) && !strcmp(ptr->db, tables->db))
+ if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
+ !strcmp(ptr->db, tables->db))
{
net_printf(thd,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */
DBUG_RETURN(0); /* purecov: tested */
@@ -4560,9 +4637,9 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
if (purge_time >= 0)
mysql_bin_log.purge_logs_before_date(purge_time);
}
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
rotate_relay_log(active_mi);
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
#endif
if (ha_flush_logs())
result=1;
@@ -4623,10 +4700,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
if (options & REFRESH_SLAVE)
{
tmp_write_to_binlog= 0;
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
if (reset_slave(thd, active_mi))
result=1;
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
}
#endif
if (options & REFRESH_USER_RESOURCES)
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 7c2913bc495..ab136668cfb 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -39,7 +39,7 @@ Prepare-execute:
- Server gets the command 'COM_EXECUTE' to execute the
previously prepared query. If there is any param markers; then client
- will send the data in the following format:
+ will send the data in the following format:
[COM_EXECUTE:1]
[STMT_ID:4]
[NULL_BITS:(param_count+7)/8)]
@@ -86,16 +86,18 @@ class Prepared_statement: public Statement
{
public:
THD *thd;
- Item_param **param; /* array of all placeholders */
+ Item_param **param_array;
uint param_count;
uint last_errno;
char last_error[MYSQL_ERRMSG_SIZE];
- bool error_in_prepare, long_data_used;
+ bool get_longdata_error;
+ bool long_data_used;
bool log_full_query;
#ifndef EMBEDDED_LIBRARY
- bool (*setup_params)(Prepared_statement *st, uchar *pos, uchar *read_pos);
+ bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
+ uchar *read_pos);
#else
- bool (*setup_params_data)(Prepared_statement *st);
+ bool (*set_params_data)(Prepared_statement *st);
#endif
public:
Prepared_statement(THD *thd_arg);
@@ -116,14 +118,7 @@ inline bool is_param_null(const uchar *pos, ulong param_no)
enum { STMT_QUERY_LOG_LENGTH= 8192 };
-#ifdef EMBEDDED_LIBRARY
-#define SETUP_PARAM_FUNCTION(fn_name) \
-static void fn_name(Item_param *param, uchar **pos, ulong data_len)
-#else
-#define SETUP_PARAM_FUNCTION(fn_name) \
-static void fn_name(Item_param *param, uchar **pos)
-#endif
-
+enum enum_send_error { DONT_SEND_ERROR= 0, SEND_ERROR };
/*
Seek prepared statement in statement map by id: returns zero if statement
@@ -131,14 +126,16 @@ static void fn_name(Item_param *param, uchar **pos)
*/
static Prepared_statement *
-find_prepared_statement(THD *thd, ulong id, const char *where)
+find_prepared_statement(THD *thd, ulong id, const char *where,
+ enum enum_send_error se)
{
Statement *stmt= thd->stmt_map.find(id);
if (stmt == 0 || stmt->type() != Statement::PREPARED_STATEMENT)
{
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), id, where);
- send_error(thd);
+ if (se == SEND_ERROR)
+ send_error(thd);
return 0;
}
return (Prepared_statement *) stmt;
@@ -154,11 +151,11 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
{
NET *net= &stmt->thd->net;
char buff[9];
- buff[0]= 0;
+ buff[0]= 0; /* OK packet indicator */
int4store(buff+1, stmt->id);
int2store(buff+5, columns);
int2store(buff+7, stmt->param_count);
- /* This should be fixed to work with prepared statements */
+ /* TODO: send types of placeholders here */
return (my_net_write(net, buff, sizeof(buff)) || net_flush(net));
}
#else
@@ -177,104 +174,138 @@ static bool send_prep_stmt(Prepared_statement *stmt,
/*
- Read the length of the parameter data and retun back to
- caller by positing the pointer to param data
+ Read the length of the parameter data and return back to
+ caller by positing the pointer to param data.
*/
#ifndef EMBEDDED_LIBRARY
-static ulong get_param_length(uchar **packet)
+static ulong get_param_length(uchar **packet, ulong len)
{
reg1 uchar *pos= *packet;
+ if (len < 1)
+ return 0;
if (*pos < 251)
{
(*packet)++;
return (ulong) *pos;
}
+ if (len < 3)
+ return 0;
if (*pos == 252)
{
(*packet)+=3;
return (ulong) uint2korr(pos+1);
}
+ if (len < 4)
+ return 0;
if (*pos == 253)
{
(*packet)+=4;
return (ulong) uint3korr(pos+1);
}
+ if (len < 5)
+ return 0;
(*packet)+=9; // Must be 254 when here
+ /* TODO: why uint4korr here? (should be uint8korr) */
return (ulong) uint4korr(pos+1);
}
#else
-#define get_param_length(A) data_len
+#define get_param_length(packet, len) len
#endif /*!EMBEDDED_LIBRARY*/
/*
- Setup param conversion routines
+ Data conversion routines
+ SYNOPSIS
+ set_param_xx()
+ param parameter item
+ pos input data buffer
+ len length of data in the buffer
- setup_param_xx()
- param Parameter Item
- pos Input data buffer
-
- All these functions reads the data from pos and sets up that data
- through 'param' and advances the buffer position to predifined
- length position.
+ All these functions read the data from pos, convert it to requested type
+ and assign to param; pos is advanced to predefined length.
Make a note that the NULL handling is examined at first execution
(i.e. when input types altered) and for all subsequent executions
we don't read any values for this.
- RETURN VALUES
-
+ RETURN VALUE
+ none
*/
-SETUP_PARAM_FUNCTION(setup_param_tiny)
+void set_param_tiny(Item_param *param, uchar **pos, ulong len)
{
+#ifndef EMBEDDED_LIBRARY
+ if (len < 1)
+ return;
+#endif
param->set_int((longlong)(**pos));
*pos+= 1;
}
-SETUP_PARAM_FUNCTION(setup_param_short)
+void set_param_short(Item_param *param, uchar **pos, ulong len)
{
+#ifndef EMBEDDED_LIBRARY
+ if (len < 2)
+ return;
+#endif
param->set_int((longlong)sint2korr(*pos));
*pos+= 2;
}
-SETUP_PARAM_FUNCTION(setup_param_int32)
+void set_param_int32(Item_param *param, uchar **pos, ulong len)
{
+#ifndef EMBEDDED_LIBRARY
+ if (len < 4)
+ return;
+#endif
param->set_int((longlong)sint4korr(*pos));
*pos+= 4;
}
-SETUP_PARAM_FUNCTION(setup_param_int64)
+void set_param_int64(Item_param *param, uchar **pos, ulong len)
{
+#ifndef EMBEDDED_LIBRARY
+ if (len < 8)
+ return;
+#endif
param->set_int((longlong)sint8korr(*pos));
*pos+= 8;
}
-SETUP_PARAM_FUNCTION(setup_param_float)
+void set_param_float(Item_param *param, uchar **pos, ulong len)
{
+#ifndef EMBEDDED_LIBRARY
+ if (len < 4)
+ return;
+#endif
float data;
float4get(data,*pos);
param->set_double((double) data);
*pos+= 4;
}
-SETUP_PARAM_FUNCTION(setup_param_double)
+void set_param_double(Item_param *param, uchar **pos, ulong len)
{
+#ifndef EMBEDDED_LIBRARY
+ if (len < 8)
+ return;
+#endif
double data;
float8get(data,*pos);
param->set_double((double) data);
*pos+= 8;
}
-SETUP_PARAM_FUNCTION(setup_param_time)
+void set_param_time(Item_param *param, uchar **pos, ulong len)
{
ulong length;
- if ((length= get_param_length(pos)))
+ if ((length= get_param_length(pos, len)) >= 8)
{
uchar *to= *pos;
- TIME tm;
+ TIME tm;
+ /* TODO: why length is compared with 8 here? */
tm.second_part= (length > 8 ) ? (ulong) sint4korr(to+7): 0;
tm.day= (ulong) sint4korr(to+1);
@@ -290,11 +321,11 @@ SETUP_PARAM_FUNCTION(setup_param_time)
*pos+= length;
}
-SETUP_PARAM_FUNCTION(setup_param_datetime)
+void set_param_datetime(Item_param *param, uchar **pos, ulong len)
{
- uint length= get_param_length(pos);
+ uint length;
- if (length)
+ if ((length= get_param_length(pos, len)) >= 4)
{
uchar *to= *pos;
TIME tm;
@@ -320,11 +351,11 @@ SETUP_PARAM_FUNCTION(setup_param_datetime)
*pos+= length;
}
-SETUP_PARAM_FUNCTION(setup_param_date)
+void set_param_date(Item_param *param, uchar **pos, ulong len)
{
ulong length;
- if ((length= get_param_length(pos)))
+ if ((length= get_param_length(pos, len)) >= 4)
{
uchar *to= *pos;
TIME tm;
@@ -342,55 +373,55 @@ SETUP_PARAM_FUNCTION(setup_param_date)
*pos+= length;
}
-SETUP_PARAM_FUNCTION(setup_param_str)
+void set_param_str(Item_param *param, uchar **pos, ulong len)
{
- ulong len= get_param_length(pos);
- param->set_value((const char *)*pos, len);
- *pos+= len;
+ ulong length= get_param_length(pos, len);
+ param->set_value((const char *)*pos, length);
+ *pos+= length;
}
-void setup_param_functions(Item_param *param, uchar param_type)
+static void setup_one_conversion_function(Item_param *param, uchar param_type)
{
switch (param_type) {
case FIELD_TYPE_TINY:
- param->setup_param_func= setup_param_tiny;
+ param->set_param_func= set_param_tiny;
param->item_result_type= INT_RESULT;
break;
case FIELD_TYPE_SHORT:
- param->setup_param_func= setup_param_short;
+ param->set_param_func= set_param_short;
param->item_result_type= INT_RESULT;
break;
case FIELD_TYPE_LONG:
- param->setup_param_func= setup_param_int32;
+ param->set_param_func= set_param_int32;
param->item_result_type= INT_RESULT;
break;
case FIELD_TYPE_LONGLONG:
- param->setup_param_func= setup_param_int64;
+ param->set_param_func= set_param_int64;
param->item_result_type= INT_RESULT;
break;
case FIELD_TYPE_FLOAT:
- param->setup_param_func= setup_param_float;
+ param->set_param_func= set_param_float;
param->item_result_type= REAL_RESULT;
break;
case FIELD_TYPE_DOUBLE:
- param->setup_param_func= setup_param_double;
+ param->set_param_func= set_param_double;
param->item_result_type= REAL_RESULT;
break;
case FIELD_TYPE_TIME:
- param->setup_param_func= setup_param_time;
+ param->set_param_func= set_param_time;
param->item_result_type= STRING_RESULT;
break;
case FIELD_TYPE_DATE:
- param->setup_param_func= setup_param_date;
+ param->set_param_func= set_param_date;
param->item_result_type= STRING_RESULT;
break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
- param->setup_param_func= setup_param_datetime;
+ param->set_param_func= set_param_datetime;
param->item_result_type= STRING_RESULT;
break;
default:
- param->setup_param_func= setup_param_str;
+ param->set_param_func= set_param_str;
param->item_result_type= STRING_RESULT;
}
}
@@ -401,14 +432,14 @@ void setup_param_functions(Item_param *param, uchar param_type)
and if binary/update log is set, generate the valid query.
*/
-static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
- uchar *read_pos)
+static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
+ uchar *read_pos, uchar *data_end)
{
- THD *thd= stmt->thd;
- List<Item> &params= stmt->lex->param_list;
- List_iterator<Item> param_iterator(params);
- Item_param *param;
-
+ THD *thd= stmt->thd;
+ Item_param **begin= stmt->param_array;
+ Item_param **end= begin + stmt->param_count;
+ uint32 length= 0;
+
String str, query;
const String *res;
@@ -417,16 +448,14 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
if (query.copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
- ulong param_no= 0;
- uint32 length= 0;
-
- while ((param= (Item_param *)param_iterator++))
+ for (Item_param **it= begin; it < end; ++it)
{
+ Item_param *param= *it;
if (param->long_data_supplied)
- res= param->query_val_str(&str);
+ res= param->query_val_str(&str);
else
{
- if (is_param_null(pos,param_no))
+ if (is_param_null(null_array, it - begin))
{
param->maybe_null= param->null_value= 1;
res= &my_null_string;
@@ -434,7 +463,9 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
else
{
param->maybe_null= param->null_value= 0;
- param->setup_param_func(param,&read_pos);
+ if (read_pos >= data_end)
+ DBUG_RETURN(1);
+ param->set_param_func(param, &read_pos, data_end - read_pos);
res= param->query_val_str(&str);
}
}
@@ -442,7 +473,6 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
DBUG_RETURN(1);
length+= res->length()-1;
- param_no++;
}
if (alloc_query(thd, (char *)query.ptr(), query.length()+1))
DBUG_RETURN(1);
@@ -451,76 +481,76 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *pos,
}
-static bool insert_params(Prepared_statement *stmt, uchar *pos,
- uchar *read_pos)
+static bool insert_params(Prepared_statement *stmt, uchar *null_array,
+ uchar *read_pos, uchar *data_end)
{
- List<Item> &params= stmt->lex->param_list;
- List_iterator<Item> param_iterator(params);
- Item_param *param;
- ulong param_no= 0;
+ Item_param **begin= stmt->param_array;
+ Item_param **end= begin + stmt->param_count;
DBUG_ENTER("insert_params");
- while ((param= (Item_param *)param_iterator++))
+ for (Item_param **it= begin; it < end; ++it)
{
- if (!param->long_data_supplied)
+ Item_param *param= *it;
+ if (!param->long_data_supplied)
{
- if (is_param_null(pos,param_no))
+ if (is_param_null(null_array, it - begin))
param->maybe_null= param->null_value= 1;
else
{
param->maybe_null= param->null_value= 0;
- param->setup_param_func(param,&read_pos);
+ if (read_pos >= data_end)
+ DBUG_RETURN(1);
+ param->set_param_func(param, &read_pos, data_end - read_pos);
}
}
- param_no++;
}
DBUG_RETURN(0);
}
-static bool setup_params_data(Prepared_statement *stmt)
-{
- List<Item> &params= stmt->lex->param_list;
- List_iterator<Item> param_iterator(params);
- Item_param *param;
- uchar *pos= (uchar*) stmt->thd->net.read_pos + 1 +
- MYSQL_STMT_HEADER; //skip header
- uchar *read_pos= pos+(stmt->param_count+7) / 8; //skip null bits
+static bool setup_conversion_functions(Prepared_statement *stmt,
+ uchar **data, uchar *data_end)
+{
+ /* skip null bits */
+ uchar *read_pos= *data + (stmt->param_count+7) / 8;
- DBUG_ENTER("setup_params_data");
+ DBUG_ENTER("setup_conversion_functions");
if (*read_pos++) //types supplied / first execute
- {
+ {
/*
First execute or types altered by the client, setup the
conversion routines for all parameters (one time)
*/
- while ((param= (Item_param *)param_iterator++))
- {
- setup_param_functions(param,*read_pos);
+ Item_param **it= stmt->param_array;
+ Item_param **end= it + stmt->param_count;
+ for (; it < end; ++it)
+ {
+ if (read_pos >= data_end)
+ DBUG_RETURN(1);
+ setup_one_conversion_function(*it, *read_pos);
read_pos+= 2;
}
- param_iterator.rewind();
- }
- stmt->setup_params(stmt,pos,read_pos);
+ }
+ *data= read_pos;
DBUG_RETURN(0);
}
#else
-bool setup_params_data(Prepared_statement *stmt)
-{
- List<Item> &params= stmt->lex->param_list;
- List_iterator<Item> param_iterator(params);
- Item_param *param;
+static bool emb_insert_params(Prepared_statement *stmt)
+{
+ Item_param **it= stmt->param_array;
+ Item_param **end= it + stmt->param_count;
MYSQL_BIND *client_param= stmt->thd->client_params;
- DBUG_ENTER("setup_params_data");
+ DBUG_ENTER("emb_insert_params");
- for (;(param= (Item_param *)param_iterator++); client_param++)
- {
- setup_param_functions(param, client_param->buffer_type);
+ for (; it < end; ++it, ++client_param)
+ {
+ Item_param *param= *it;
+ setup_one_conversion_function(param, client_param->buffer_type);
if (!param->long_data_supplied)
{
if (*client_param->is_null)
@@ -529,39 +559,39 @@ bool setup_params_data(Prepared_statement *stmt)
{
uchar *buff= (uchar*)client_param->buffer;
param->maybe_null= param->null_value= 0;
- param->setup_param_func(param,&buff,
- client_param->length ?
- *client_param->length :
- client_param->buffer_length);
+ param->set_param_func(param, &buff,
+ client_param->length ?
+ *client_param->length :
+ client_param->buffer_length);
}
}
}
DBUG_RETURN(0);
}
-bool setup_params_data_withlog(Prepared_statement *stmt)
-{
+
+static bool emb_insert_params_withlog(Prepared_statement *stmt)
+{
THD *thd= stmt->thd;
- List<Item> &params= stmt->lex->param_list;
- List_iterator<Item> param_iterator(params);
- Item_param *param;
+ Item_param **it= stmt->param_array;
+ Item_param **end= it + stmt->param_count;
MYSQL_BIND *client_param= thd->client_params;
String str, query;
const String *res;
+ uint32 length= 0;
- DBUG_ENTER("setup_params_data_withlog");
+ DBUG_ENTER("emb_insert_params_withlog");
if (query.copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
- uint32 length= 0;
-
- for (;(param= (Item_param *)param_iterator++); client_param++)
- {
- setup_param_functions(param, client_param->buffer_type);
+ for (; it < end; ++it, ++client_param)
+ {
+ Item_param *param= *it;
+ setup_one_conversion_function(param, client_param->buffer_type);
if (param->long_data_supplied)
- res= param->query_val_str(&str);
+ res= param->query_val_str(&str);
else
{
if (*client_param->is_null)
@@ -573,16 +603,15 @@ bool setup_params_data_withlog(Prepared_statement *stmt)
{
uchar *buff= (uchar*)client_param->buffer;
param->maybe_null= param->null_value= 0;
- param->setup_param_func(param,&buff,
- client_param->length ?
- *client_param->length :
- client_param->buffer_length);
+ param->set_param_func(param, &buff,
+ client_param->length ?
+ *client_param->length :
+ client_param->buffer_length);
res= param->query_val_str(&str);
}
}
if (query.replace(param->pos_in_query+length, 1, *res))
DBUG_RETURN(1);
-
length+= res->length()-1;
}
@@ -595,15 +624,21 @@ bool setup_params_data_withlog(Prepared_statement *stmt)
#endif /*!EMBEDDED_LIBRARY*/
/*
- Validate the following information for INSERT statement:
- - field existance
- - fields count
+ Validate the following information for INSERT statement:
+ - field existence
+ - fields count
+ SYNOPSIS
+ mysql_test_insert_fields()
+ RETURN VALUE
+ 0 ok
+ 1 error, sent to the client
+ -1 error, not sent to client
*/
-static bool mysql_test_insert_fields(Prepared_statement *stmt,
- TABLE_LIST *table_list,
- List<Item> &fields,
- List<List_item> &values_list)
+static int mysql_test_insert_fields(Prepared_statement *stmt,
+ TABLE_LIST *table_list,
+ List<Item> &fields,
+ List<List_item> &values_list)
{
THD *thd= stmt->thd;
TABLE *table;
@@ -630,7 +665,7 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
if (open_and_lock_tables(thd, table_list))
{
thd->free_temporary_memory_pool_for_ps_preparing();
- DBUG_RETURN(1);
+ DBUG_RETURN(-1);
}
table= table_list->table;
@@ -643,7 +678,7 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
if (check_insert_fields(thd,table,fields,*values,1))
{
thd->free_temporary_memory_pool_for_ps_preparing();
- DBUG_RETURN(1);
+ DBUG_RETURN(-1);
}
thd->free_temporary_memory_pool_for_ps_preparing();
@@ -658,7 +693,7 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
ER(ER_WRONG_VALUE_COUNT_ON_ROW),
MYF(0), counter);
- DBUG_RETURN(1);
+ DBUG_RETURN(-1);
}
}
}
@@ -666,25 +701,26 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
{
thd->free_temporary_memory_pool_for_ps_preparing();
}
- if (send_prep_stmt(stmt, 0))
- DBUG_RETURN(1);
DBUG_RETURN(0);
}
/*
- Validate the following information
- UPDATE - set and where clause DELETE - where clause
-
- And send update-set clause column list fields info
- back to client. For DELETE, just validate where clause
- and return no fields information back to client.
+ Validate the following information:
+ UPDATE - set and where clause
+ DELETE - where clause
+ SYNOPSIS
+ mysql_test_upd_fields()
+ RETURN VALUE
+ 0 success
+ 1 error, sent to client
+ -1 error, not sent to client
*/
-static bool mysql_test_upd_fields(Prepared_statement *stmt,
- TABLE_LIST *table_list,
- List<Item> &fields, List<Item> &values,
- COND *conds)
+static int mysql_test_upd_fields(Prepared_statement *stmt,
+ TABLE_LIST *table_list,
+ List<Item> &fields, List<Item> &values,
+ COND *conds)
{
THD *thd= stmt->thd;
@@ -711,44 +747,43 @@ static bool mysql_test_upd_fields(Prepared_statement *stmt,
thd->free_temporary_memory_pool_for_ps_preparing();
- /*
- Currently return only column list info only, and we are not
- sending any info on where clause.
- */
- if (send_prep_stmt(stmt, 0))
- DBUG_RETURN(1);
+ /* TODO: here we should send types of placeholders to the client. */
DBUG_RETURN(0);
err:
thd->free_temporary_memory_pool_for_ps_preparing();
- DBUG_RETURN(1);
+ DBUG_RETURN(-1);
}
/*
- Validate the following information:
-
+ Validate the following information:
SELECT - column list
- where clause
- order clause
- having clause
- group by clause
- if no column spec i.e. '*', then setup all fields
-
- And send column list fields info back to client.
+ In case of success, if this query is not EXPLAIN, send column list info
+ back to client.
+ SYNOPSIS
+ mysql_test_select_fields()
+ RETURN VALUE
+ 0 success
+ 1 error, sent to client
+ -1 error, not sent to client
*/
-static bool mysql_test_select_fields(Prepared_statement *stmt,
- TABLE_LIST *tables,
- uint wild_num,
- List<Item> &fields, COND *conds,
- uint og_num, ORDER *order, ORDER *group,
- Item *having, ORDER *proc,
- ulong select_options,
- SELECT_LEX_UNIT *unit,
- SELECT_LEX *select_lex)
+static int mysql_test_select_fields(Prepared_statement *stmt,
+ TABLE_LIST *tables,
+ uint wild_num,
+ List<Item> &fields, COND *conds,
+ uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc,
+ ulong select_options,
+ SELECT_LEX_UNIT *unit,
+ SELECT_LEX *select_lex)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
- select_result *result= lex->result;
DBUG_ENTER("mysql_test_select_fields");
@@ -772,7 +807,10 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
*/
thd->allocate_temporary_memory_pool_for_ps_preparing();
if (open_and_lock_tables(thd, tables))
+ {
+ send_error(thd);
goto err;
+ }
if (lex->describe)
{
@@ -781,23 +819,27 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
}
else
{
+ select_result *result= lex->result;
if (!result && !(result= new select_send()))
{
send_error(thd, ER_OUT_OF_RESOURCES);
goto err;
}
- thd->used_tables= 0; // Updated by setup_fields
+ thd->used_tables= 0; // Updated by setup_fields
if (unit->prepare(thd, result, 0))
+ {
+ send_error(thd);
goto err_prep;
+ }
if (send_prep_stmt(stmt, fields.elements) ||
thd->protocol_simple.send_fields(&fields, 0)
#ifndef EMBEDDED_LIBRARY
- || net_flush(&thd->net)
+ || net_flush(&thd->net)
#endif
- )
+ )
goto err_prep;
unit->cleanup();
@@ -814,97 +856,104 @@ err:
/*
- Send the prepare query results back to client
+ Send the prepare query results back to client
+ SYNOPSIS
+ send_prepare_results()
+ stmt prepared statement
+ RETURN VALUE
+ 0 success
+ 1 error, sent to client
*/
-static bool send_prepare_results(Prepared_statement *stmt)
+static int send_prepare_results(Prepared_statement *stmt)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
+ SELECT_LEX *select_lex= &lex->select_lex;
+ TABLE_LIST *tables=(TABLE_LIST*) select_lex->table_list.first;
enum enum_sql_command sql_command= lex->sql_command;
+ int res;
DBUG_ENTER("send_prepare_results");
DBUG_PRINT("enter",("command: %d, param_count: %ld",
- sql_command, lex->param_count));
-
- /* Setup prepared stmt */
- stmt->param_count= lex->param_count;
-
- SELECT_LEX *select_lex= &lex->select_lex;
- TABLE_LIST *tables=(TABLE_LIST*) select_lex->table_list.first;
+ sql_command, stmt->param_count));
switch (sql_command) {
case SQLCOM_INSERT:
- if (mysql_test_insert_fields(stmt, tables, lex->field_list,
- lex->many_values))
- goto abort;
+ if ((res= mysql_test_insert_fields(stmt, tables, lex->field_list,
+ lex->many_values)))
+ goto error;
break;
case SQLCOM_UPDATE:
- if (mysql_test_upd_fields(stmt, tables, select_lex->item_list,
- lex->value_list, select_lex->where))
- goto abort;
- break;
-
+ /* XXX: fallthrough */
case SQLCOM_DELETE:
- if (mysql_test_upd_fields(stmt, tables, select_lex->item_list,
- lex->value_list, select_lex->where))
- goto abort;
+ if ((res= mysql_test_upd_fields(stmt, tables, select_lex->item_list,
+ lex->value_list, select_lex->where)))
+ goto error;
break;
case SQLCOM_SELECT:
- if (mysql_test_select_fields(stmt, tables, select_lex->with_wild,
- select_lex->item_list,
- select_lex->where,
- select_lex->order_list.elements +
- select_lex->group_list.elements,
- (ORDER*) select_lex->order_list.first,
- (ORDER*) select_lex->group_list.first,
- select_lex->having,
- (ORDER*)lex->proc_list.first,
- select_lex->options | thd->options,
- &(lex->unit), select_lex))
- goto abort;
- break;
+ if ((res= mysql_test_select_fields(stmt, tables, select_lex->with_wild,
+ select_lex->item_list,
+ select_lex->where,
+ select_lex->order_list.elements +
+ select_lex->group_list.elements,
+ (ORDER*) select_lex->order_list.first,
+ (ORDER*) select_lex->group_list.first,
+ select_lex->having,
+ (ORDER*)lex->proc_list.first,
+ select_lex->options | thd->options,
+ &(lex->unit), select_lex)))
+ goto error;
+ /* Statement and field info has already been sent */
+ DBUG_RETURN(0);
default:
- {
- /*
- Rest fall through to default category, no parsing
- for non-DML statements
- */
- if (send_prep_stmt(stmt, 0))
- goto abort;
- }
+ /*
+ Rest fall through to default category, no parsing
+ for non-DML statements
+ */
+ break;
}
- DBUG_RETURN(0);
+ DBUG_RETURN(send_prep_stmt(stmt, 0));
-abort:
- send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
+error:
+ if (res < 0)
+ send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0);
DBUG_RETURN(1);
}
/*
- Initialize parameter items in statement
+ Initialize array of parametes in statement from LEX.
+ (We need to have quick access to items by number in mysql_send_longdata).
+ This is to avoid using malloc/realloc in the parser.
*/
-static bool init_param_items(Prepared_statement *stmt)
+static bool init_param_array(Prepared_statement *stmt)
{
- Item_param **to;
-
- if (!stmt->param_count)
- stmt->param= (Item_param **)0;
- else
- {
- if (!(stmt->param= to= (Item_param **)
- my_malloc(sizeof(Item_param *)*(stmt->param_count+1),
- MYF(MY_WME))))
+ LEX *lex= stmt->lex;
+ if ((stmt->param_count= lex->param_list.elements))
+ {
+ Item_param **to;
+ List_iterator<Item_param> param_iterator(lex->param_list);
+ /* Use thd->mem_root as it points at statement mem_root */
+ stmt->param_array= (Item_param **)
+ alloc_root(&stmt->thd->mem_root,
+ sizeof(Item_param*) * stmt->param_count);
+ if (!stmt->param_array)
+ {
+ send_error(stmt->thd, ER_OUT_OF_RESOURCES);
return 1;
-
- List_iterator<Item> param_iterator(stmt->lex->param_list);
- while ((*(to++)= (Item_param *)param_iterator++));
- }
+ }
+ for (to= stmt->param_array;
+ to < stmt->param_array + stmt->param_count;
+ ++to)
+ {
+ *to= param_iterator++;
+ }
+ }
return 0;
}
@@ -912,137 +961,104 @@ static bool init_param_items(Prepared_statement *stmt)
/*
Parse the query and send the total number of parameters
and resultset metadata information back to client (if any),
- without executing the query i.e. with out any log/disk
+ without executing the query i.e. without any log/disk
writes. This will allow the queries to be re-executed
- without re-parsing during execute.
-
- If parameter markers are found in the query, then store
- the information using Item_param along with maintaining a
- list in lex->param_list, so that a fast and direct
- retrieval can be made without going through all field
- items.
+ without re-parsing during execute.
+
+ If parameter markers are found in the query, then store
+ the information using Item_param along with maintaining a
+ list in lex->param_array, so that a fast and direct
+ retrieval can be made without going through all field
+ items.
*/
-bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
+void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
{
LEX *lex;
Prepared_statement *stmt= new Prepared_statement(thd);
- SELECT_LEX *sl;
+ int error;
DBUG_ENTER("mysql_stmt_prepare");
if (stmt == 0)
- DBUG_RETURN(0);
+ {
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ DBUG_VOID_RETURN;
+ }
if (thd->stmt_map.insert(stmt))
- goto insert_stmt_err;
+ {
+ delete stmt;
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ DBUG_VOID_RETURN;
+ }
thd->stmt_backup.set_statement(thd);
+ thd->stmt_backup.set_item_arena(thd);
thd->set_statement(stmt);
- thd->current_statement= stmt;
+ thd->set_item_arena(stmt);
if (alloc_query(thd, packet, packet_length))
- goto alloc_query_err;
+ {
+ stmt->set_statement(thd);
+ stmt->set_item_arena(thd);
+ thd->set_statement(&thd->stmt_backup);
+ thd->set_item_arena(&thd->stmt_backup);
+ /* Statement map deletes statement on erase */
+ thd->stmt_map.erase(stmt);
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ DBUG_VOID_RETURN;
+ }
- mysql_log.write(thd, COM_PREPARE, "%s", packet);
+ mysql_log.write(thd, COM_PREPARE, "%s", packet);
+ thd->current_statement= stmt;
lex= lex_start(thd, (uchar *) thd->query, thd->query_length);
mysql_init_query(thd);
lex->safe_to_cache_query= 0;
- lex->param_count= 0;
-
- if (yyparse((void *)thd) || thd->is_fatal_error || send_prepare_results(stmt))
- goto yyparse_err;
- lex_end(lex);
+ error= yyparse((void *)thd) || thd->is_fatal_error ||
+ init_param_array(stmt) ||
+ send_prepare_results(stmt);
+ /* restore to WAIT_PRIOR: QUERY_PRIOR is set inside alloc_query */
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
-
- // save WHERE clause pointers to avoid damaging they by optimisation
- for (sl= thd->lex->all_selects_list;
- sl;
- sl= sl->next_select_in_list())
- {
- sl->prep_where= sl->where;
- }
-
- stmt->set_statement(thd);
- thd->set_statement(&thd->stmt_backup);
- thd->current_statement= 0;
-
- if (init_param_items(stmt))
- goto init_param_err;
-
- stmt->command= COM_EXECUTE; // set it only once here
-
- DBUG_RETURN(0);
-
-yyparse_err:
lex_end(lex);
stmt->set_statement(thd);
+ stmt->set_item_arena(thd);
thd->set_statement(&thd->stmt_backup);
-init_param_err:
-alloc_query_err:
- /* Statement map deletes statement on erase */
- thd->stmt_map.erase(stmt);
- thd->current_statement= 0;
- DBUG_RETURN(1);
-insert_stmt_err:
- stmt->set_statement(thd);
- thd->set_statement(&thd->stmt_backup);
- /* Statement map deletes statement on erase */
- thd->stmt_map.erase(stmt);
+ thd->set_item_arena(&thd->stmt_backup);
thd->current_statement= 0;
- delete stmt;
- DBUG_RETURN(1);
-}
-
-
-/*
- Executes previously prepared query
-
- If there is any parameters (stmt->param_count), then replace
- markers with the data supplied from client, and then
- execute the query
-*/
-void mysql_stmt_execute(THD *thd, char *packet)
-{
- ulong stmt_id= uint4korr(packet);
- Prepared_statement *stmt;
-
- DBUG_ENTER("mysql_stmt_execute");
-
- if (!(stmt= find_prepared_statement(thd, stmt_id, "execute")))
- DBUG_VOID_RETURN;
-
- /* Check if we got an error when sending long data */
- if (stmt->error_in_prepare)
+ if (error)
{
- send_error(thd, stmt->last_errno, stmt->last_error);
- DBUG_VOID_RETURN;
+ /* Statement map deletes statement on erase */
+ thd->stmt_map.erase(stmt);
+ /* error is sent inside yyparse/send_prepare_results */
}
+ else
+ {
+ SELECT_LEX *sl= stmt->lex->all_selects_list;
+ /*
+ Save WHERE clause pointers, because they may be changed during query
+ optimisation.
+ */
+ for (; sl; sl= sl->next_select_in_list())
+ {
+ sl->prep_where= sl->where;
+ }
+ }
+ DBUG_VOID_RETURN;
+}
- stmt->query_id= thd->query_id;
- thd->stmt_backup.set_statement(thd);
- thd->set_statement(stmt);
- thd->free_list= 0;
-
- /*
- To make sure that all runtime data is stored in its own memory root and
- does not interfere with data possibly present in thd->mem_root.
- This root is cleaned up in the end of execution.
- FIXME: to be replaced with more efficient approach, and verified why we
- can not use thd->mem_root safely.
- */
- init_sql_alloc(&thd->mem_root,
- thd->variables.query_alloc_block_size,
- thd->variables.query_prealloc_size);
+/* Reinit statement before execution */
+static void reset_stmt_for_execute(Prepared_statement *stmt)
+{
+ THD *thd= stmt->thd;
+ SELECT_LEX *sl= stmt->lex->all_selects_list;
- for (SELECT_LEX *sl= stmt->lex->all_selects_list;
- sl;
- sl= sl->next_select_in_list())
+ for (; sl; sl= sl->next_select_in_list())
{
/*
Copy WHERE clause pointers to avoid damaging they by optimisation
@@ -1075,96 +1091,147 @@ void mysql_stmt_execute(THD *thd, char *packet)
SELECT_LEX_UNIT *unit= sl->master_unit();
unit->unclean();
unit->types.empty();
- // for derived tables & PS (which can't be reset by Item_subquery)
+ /* for derived tables & PS (which can't be reset by Item_subquery) */
unit->reinit_exec_mechanism();
}
}
+}
+
+/*
+ Executes previously prepared query.
+ If there is any parameters, then replace markers with the data supplied
+ from client, and then execute the query.
+ SYNOPSYS
+ mysql_stmt_execute()
+*/
+
+void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
+{
+ ulong stmt_id= uint4korr(packet);
+ Prepared_statement *stmt;
+
+ DBUG_ENTER("mysql_stmt_execute");
+
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "execute", SEND_ERROR)))
+ DBUG_VOID_RETURN;
+
+ /* Check if we got an error when sending long data */
+ if (stmt->get_longdata_error)
+ {
+ send_error(thd, stmt->last_errno, stmt->last_error);
+ DBUG_VOID_RETURN;
+ }
+
+ thd->stmt_backup.set_statement(thd);
+ thd->set_statement(stmt);
+
+ reset_stmt_for_execute(stmt);
#ifndef EMBEDDED_LIBRARY
- if (stmt->param_count && setup_params_data(stmt))
- goto end;
+ if (stmt->param_count)
+ {
+ uchar *packet_end= (uchar *) packet + packet_length - 1;
+ packet+= 4;
+ uchar *null_array= (uchar *) packet;
+ if (setup_conversion_functions(stmt, (uchar **) &packet, packet_end) ||
+ stmt->set_params(stmt, null_array, (uchar *) packet, packet_end))
+ goto set_params_data_err;
+ }
#else
- if (stmt->param_count && (*stmt->setup_params_data)(stmt))
- goto end;
+ /*
+ In embedded library we re-install conversion routines each time
+ we set params, and also we don't need to parse packet.
+ So we do it in one function.
+ */
+ if (stmt->param_count && stmt->set_params_data(stmt))
+ goto set_params_data_err;
#endif
if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+ my_pthread_setprio(pthread_self(),QUERY_PRIOR);
/*
TODO:
Also, have checks on basic executions such as mysql_insert(),
mysql_delete(), mysql_update() and mysql_select() to not to
have re-check on setup_* and other things ..
- */
- thd->protocol= &thd->protocol_prep; // Switch to binary protocol
+ */
+ thd->protocol= &thd->protocol_prep; // Switch to binary protocol
mysql_execute_command(thd);
- thd->protocol= &thd->protocol_simple; // Use normal protocol
+ thd->protocol= &thd->protocol_simple; // Use normal protocol
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
- free_items(thd->free_list);
cleanup_items(stmt->free_list);
close_thread_tables(thd); // to close derived tables
- free_root(&thd->mem_root, MYF(0));
thd->set_statement(&thd->stmt_backup);
-end:
+ DBUG_VOID_RETURN;
+
+set_params_data_err:
+ thd->set_statement(&thd->stmt_backup);
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_execute");
+ send_error(thd);
DBUG_VOID_RETURN;
}
/*
- Reset a prepared statement
-
+ Reset a prepared statement, in case there was an error in send_longdata.
+ Note: we don't send any reply to that command.
SYNOPSIS
mysql_stmt_reset()
thd Thread handle
- packet Packet with stmt handle
+ packet Packet with stmt id
DESCRIPTION
This function is useful when one gets an error after calling
- mysql_stmt_getlongdata() and one wants to reset the handle
+ mysql_stmt_getlongdata() and wants to reset the handle
so that one can call execute again.
+ See also bug #1664
*/
void mysql_stmt_reset(THD *thd, char *packet)
{
+ /* There is always space for 4 bytes in buffer */
ulong stmt_id= uint4korr(packet);
Prepared_statement *stmt;
DBUG_ENTER("mysql_stmt_reset");
- if (!(stmt= find_prepared_statement(thd, stmt_id, "reset")))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "reset", DONT_SEND_ERROR)))
DBUG_VOID_RETURN;
- stmt->error_in_prepare= 0;
- Item_param *item= *stmt->param, *end= item + stmt->param_count;
+ stmt->get_longdata_error= 0;
/* Free long data if used */
if (stmt->long_data_used)
{
+ Item_param **item= stmt->param_array;
+ Item_param **end= item + stmt->param_count;
stmt->long_data_used= 0;
for (; item < end ; item++)
- item->reset();
+ (**item).reset();
}
DBUG_VOID_RETURN;
}
/*
- Delete a prepared statement from memory
+ Delete a prepared statement from memory.
+ Note: we don't send any reply to that command.
*/
void mysql_stmt_free(THD *thd, char *packet)
{
+ /* There is always space for 4 bytes in packet buffer */
ulong stmt_id= uint4korr(packet);
Prepared_statement *stmt;
DBUG_ENTER("mysql_stmt_free");
- if (!(stmt= find_prepared_statement(thd, stmt_id, "close")))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "close", DONT_SEND_ERROR)))
DBUG_VOID_RETURN;
/* Statement map deletes statement on erase */
@@ -1174,7 +1241,7 @@ void mysql_stmt_free(THD *thd, char *packet)
/*
- Long data in pieces from client
+ Long data in pieces from client
SYNOPSIS
mysql_stmt_get_longdata()
@@ -1210,14 +1277,15 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
ulong stmt_id= uint4korr(pos);
uint param_number= uint2korr(pos+4);
- if (!(stmt=find_prepared_statement(thd, stmt_id, "get_longdata")))
+ if (!(stmt=find_prepared_statement(thd, stmt_id, "get_longdata",
+ DONT_SEND_ERROR)))
DBUG_VOID_RETURN;
#ifndef EMBEDDED_LIBRARY
if (param_number >= stmt->param_count)
{
/* Error will be sent in execute call */
- stmt->error_in_prepare= 1;
+ stmt->get_longdata_error= 1;
stmt->last_errno= ER_WRONG_ARGUMENTS;
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), "get_longdata");
DBUG_VOID_RETURN;
@@ -1225,7 +1293,7 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
pos+= MYSQL_LONG_DATA_HEADER; // Point to data
#endif
- Item_param *param= *(stmt->param+param_number);
+ Item_param *param= stmt->param_array[param_number];
#ifndef EMBEDDED_LIBRARY
param->set_longdata(pos, packet_length-MYSQL_LONG_DATA_HEADER-1);
#else
@@ -1239,10 +1307,10 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
Prepared_statement::Prepared_statement(THD *thd_arg)
:Statement(thd_arg),
thd(thd_arg),
- param(0),
+ param_array(0),
param_count(0),
last_errno(0),
- error_in_prepare(0),
+ get_longdata_error(0),
long_data_used(0),
log_full_query(0)
{
@@ -1251,23 +1319,22 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
{
log_full_query= 1;
#ifndef EMBEDDED_LIBRARY
- setup_params= insert_params_withlog;
+ set_params= insert_params_withlog;
#else
- setup_params_data= setup_params_data_withlog;
+ set_params_data= emb_insert_params_withlog;
#endif
}
else
#ifndef EMBEDDED_LIBRARY
- setup_params= insert_params; // not fully qualified query
+ set_params= insert_params;
#else
- setup_params_data= ::setup_params_data;
+ set_params_data= emb_insert_params;
#endif
}
Prepared_statement::~Prepared_statement()
{
- my_free((char *) param, MYF(MY_ALLOW_ZERO_PTR));
free_items(free_list);
}
@@ -1277,4 +1344,3 @@ Statement::Type Prepared_statement::type() const
return PREPARED_STATEMENT;
}
-
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 8a5a9564d3e..32c5f0bfdab 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -662,8 +662,6 @@ err:
int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
{
int slave_errno= 0;
- if (!thd)
- thd = current_thd;
int thread_mask;
DBUG_ENTER("start_slave");
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 7c1a5ad67b4..94bedd9bfa2 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -70,8 +70,10 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
uint select_options, const char *info,
Item *having, Procedure *proc,
SELECT_LEX_UNIT *unit);
-static COND *optimize_cond(COND *conds,Item::cond_result *cond_value);
-static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value);
+static COND *optimize_cond(THD *thd, COND *conds,
+ Item::cond_result *cond_value);
+static COND *remove_eq_conds(THD *thd, COND *cond,
+ Item::cond_result *cond_value);
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
@@ -286,6 +288,10 @@ JOIN::prepare(Item ***rref_pointer_array,
{
DBUG_ENTER("JOIN::prepare");
+ // to prevent double initialization on EXPLAIN
+ if (optimized)
+ DBUG_RETURN(0);
+
conds= conds_init;
order= order_init;
group_list= group_init;
@@ -315,8 +321,9 @@ JOIN::prepare(Item ***rref_pointer_array,
thd->where="having clause";
thd->allow_sum_func=1;
select_lex->having_fix_field= 1;
- bool having_fix_rc= (having->fix_fields(thd, tables_list, &having) ||
- having->check_cols(1));
+ bool having_fix_rc= (!having->fixed &&
+ (having->fix_fields(thd, tables_list, &having) ||
+ having->check_cols(1)));
select_lex->having_fix_field= 0;
if (having_fix_rc || thd->net.report_error)
DBUG_RETURN(-1); /* purecov: inspected */
@@ -518,7 +525,7 @@ JOIN::optimize()
}
#endif
- conds= optimize_cond(conds,&cond_value);
+ conds= optimize_cond(thd, conds, &cond_value);
if (thd->net.report_error)
{
error= 1;
@@ -584,7 +591,10 @@ JOIN::optimize()
DBUG_RETURN(1); // error == -1
}
if (const_table_map != found_const_table_map &&
- !(select_options & SELECT_DESCRIBE))
+ !(select_options & SELECT_DESCRIBE) &&
+ (!conds ||
+ !(conds->used_tables() & RAND_TABLE_BIT) ||
+ select_lex->master_unit() == &thd->lex->unit)) // upper level SELECT
{
zero_result_cause= "no matching row in const table";
DBUG_PRINT("error",("Error: %s", zero_result_cause));
@@ -842,8 +852,7 @@ JOIN::optimize()
for (uint i_h = const_tables; i_h < tables; i_h++)
{
TABLE* table_h = join_tab[i_h].table;
- if (table_h->db_type == DB_TYPE_INNODB)
- table_h->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ table_h->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
}
}
#endif
@@ -1419,9 +1428,17 @@ JOIN::exec()
if (!curr_table->select->cond)
curr_table->select->cond= sort_table_cond;
else // This should never happen
+ {
if (!(curr_table->select->cond=
- new Item_cond_and(curr_table->select->cond, sort_table_cond)))
+ new Item_cond_and(curr_table->select->cond,
+ sort_table_cond)))
DBUG_VOID_RETURN;
+ /*
+ Item_cond_and do not need fix_fields for execution, its parameters
+ are fixed or do not need fix_fields, too
+ */
+ curr_table->select->cond->quick_fix_field();
+ }
curr_table->select_cond= curr_table->select->cond;
curr_table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(curr_table->select->cond,
@@ -2636,6 +2653,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
ha_rows rec;
double tmp;
THD *thd= join->thd;
+ if (thd->killed) // Abort
+ return;
if (!rest_tables)
{
@@ -3266,8 +3285,12 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
keyuse,join->const_table_map,
&keyinfo->key_part[i],
(char*) key_buff,maybe_null);
- /* Remmeber if we are going to use REF_OR_NULL */
- if (keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL)
+ /*
+ Remeber if we are going to use REF_OR_NULL
+ But only if field _really_ can be null i.e. we force JT_REF
+ instead of JT_REF_OR_NULL in case if field can't be null
+ */
+ if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
null_ref_key= key_buff;
key_buff+=keyinfo->key_part[i].store_length;
}
@@ -3408,7 +3431,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
table_map used_tables;
if (join->tables > 1)
cond->update_used_tables(); // Tablenr may have changed
- if (join->const_tables == join->tables)
+ if (join->const_tables == join->tables &&
+ join->thd->lex->current_select->master_unit() ==
+ &join->thd->lex->unit) // not upper level SELECT
join->const_table_map|=RAND_TABLE_BIT;
{ // Check const tables
COND *const_cond=
@@ -3443,6 +3468,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
tab->type=JT_ALL;
use_quick_range=1;
tab->use_quick=1;
+ tab->ref.key= -1;
tab->ref.key_parts=0; // Don't use ref key.
join->best_positions[i].records_read= rows2double(tab->quick->records);
}
@@ -3510,7 +3536,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{
/* Join with outer join condition */
COND *orig_cond=sel->cond;
- sel->cond=and_conds(sel->cond,tab->on_expr);
+ sel->cond=and_conds(sel->cond, tab->on_expr, 0);
if (sel->test_quick_select(join->thd, tab->keys,
used_tables & ~ current_map,
(join->select_options &
@@ -4330,6 +4356,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
SYNPOSIS
eliminate_not_funcs()
+ thd thread handler
cond condition tree
DESCRIPTION
@@ -4346,7 +4373,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
New condition tree
*/
-COND *eliminate_not_funcs(COND *cond)
+COND *eliminate_not_funcs(THD *thd, COND *cond)
{
if (!cond)
return cond;
@@ -4356,7 +4383,7 @@ COND *eliminate_not_funcs(COND *cond)
Item *item;
while ((item= li++))
{
- Item *new_item= eliminate_not_funcs(item);
+ Item *new_item= eliminate_not_funcs(thd, item);
if (item != new_item)
VOID(li.replace(new_item)); /* replace item with a new condition */
}
@@ -4364,14 +4391,13 @@ COND *eliminate_not_funcs(COND *cond)
else if (cond->type() == Item::FUNC_ITEM && /* 'NOT' operation? */
((Item_func*) cond)->functype() == Item_func::NOT_FUNC)
{
- COND *new_cond= ((Item_func*) cond)->arguments()[0]->neg_transformer();
+ COND *new_cond= ((Item_func*) cond)->arguments()[0]->neg_transformer(thd);
if (new_cond)
{
/*
Here we can delete the NOT function. Something like: delete cond;
But we don't need to do it. All items will be deleted later at once.
*/
- new_cond->fix_fields(current_thd, 0, &new_cond);
cond= new_cond;
}
}
@@ -4380,7 +4406,7 @@ COND *eliminate_not_funcs(COND *cond)
static COND *
-optimize_cond(COND *conds,Item::cond_result *cond_value)
+optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value)
{
DBUG_ENTER("optimize_cond");
if (!conds)
@@ -4390,7 +4416,7 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
}
DBUG_EXECUTE("where",print_where(conds,"original"););
/* eliminate NOT operators */
- conds= eliminate_not_funcs(conds);
+ conds= eliminate_not_funcs(thd, conds);
DBUG_EXECUTE("where", print_where(conds, "after negation elimination"););
/* change field = field to field = const for each found field = const */
propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds);
@@ -4399,7 +4425,7 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
Remove all and-levels where CONST item != CONST item
*/
DBUG_EXECUTE("where",print_where(conds,"after const change"););
- conds=remove_eq_conds(conds,cond_value) ;
+ conds= remove_eq_conds(thd, conds, cond_value) ;
DBUG_EXECUTE("info",print_where(conds,"after remove"););
DBUG_RETURN(conds);
}
@@ -4414,7 +4440,7 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
*/
static COND *
-remove_eq_conds(COND *cond,Item::cond_result *cond_value)
+remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
{
if (cond->type() == Item::COND_ITEM)
{
@@ -4428,7 +4454,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
Item *item;
while ((item=li++))
{
- Item *new_item=remove_eq_conds(item,&tmp_cond_value);
+ Item *new_item=remove_eq_conds(thd, item, &tmp_cond_value);
if (!new_item)
li.remove();
else if (item != new_item)
@@ -4462,7 +4488,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
}
}
if (should_fix_fields)
- cond->fix_fields(current_thd,0, &cond);
+ cond->update_used_tables();
if (!((Item_cond*) cond)->argument_list()->elements ||
*cond_value != Item::COND_OK)
@@ -4489,7 +4515,6 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
Item_func_isnull *func=(Item_func_isnull*) cond;
Item **args= func->arguments();
- THD *thd=current_thd;
if (args[0]->type() == Item::FIELD_ITEM)
{
Field *field=((Item_field*) args[0])->field;
@@ -5453,13 +5478,22 @@ free_tmp_table(THD *thd, TABLE *entry)
save_proc_info=thd->proc_info;
thd->proc_info="removing tmp table";
free_blobs(entry);
- if (entry->db_stat && entry->file)
+ if (entry->file)
{
- (void) entry->file->close();
+ if (entry->db_stat)
+ {
+ (void) entry->file->close();
+ }
+ /*
+ We can't call ha_delete_table here as the table may created in mixed case
+ here and we have to ensure that delete_table gets the table name in
+ the original case.
+ */
+ if (!(test_flags & TEST_KEEP_TMP_TABLES) || entry->db_type == DB_TYPE_HEAP)
+ entry->file->delete_table(entry->real_name);
delete entry->file;
}
- if (!(test_flags & TEST_KEEP_TMP_TABLES) || entry->db_type == DB_TYPE_HEAP)
- (void) ha_delete_table(entry->db_type,entry->real_name);
+
/* free blobs */
for (Field **ptr=entry->field ; *ptr ; ptr++)
(*ptr)->free();
@@ -5762,7 +5796,15 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
return 0;
}
else
+ {
+ /*
+ This row failed selection, release lock on it.
+ XXX: There is no table handler in MySQL which makes use of this
+ call. It's kept from Gemini times. A lot of new code was added
+ recently (i. e. subselects) without having it in mind.
+ */
info->file->unlock_row();
+ }
}
} while (!(error=info->read_record(info)) && !(*report_error));
}
@@ -5924,8 +5966,8 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
if (tab->on_expr && !table->null_row)
{
if ((table->null_row= test(tab->on_expr->val_int() == 0)))
- empty_record(table);
- }
+ mark_as_null_row(table);
+ }
if (!table->null_row)
table->maybe_null=0;
DBUG_RETURN(0);
@@ -6733,7 +6775,7 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
static COND *
-make_cond_for_table(COND *cond,table_map tables,table_map used_table)
+make_cond_for_table(COND *cond, table_map tables, table_map used_table)
{
if (used_table && !(cond->used_tables() & used_table))
return (COND*) 0; // Already checked
@@ -6759,7 +6801,13 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
case 1:
return new_cond->argument_list()->head();
default:
- new_cond->used_tables_cache=((Item_cond*) cond)->used_tables_cache &
+ /*
+ Item_cond_and do not need fix_fields for execution, its parameters
+ are fixed or do not need fix_fields, too
+ */
+ new_cond->quick_fix_field();
+ new_cond->used_tables_cache=
+ ((Item_cond_and*) cond)->used_tables_cache &
tables;
return new_cond;
}
@@ -6778,7 +6826,12 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
return (COND*) 0; // Always true
new_cond->argument_list()->push_back(fix);
}
- new_cond->used_tables_cache=((Item_cond_or*) cond)->used_tables_cache;
+ /*
+ Item_cond_and do not need fix_fields for execution, its parameters
+ are fixed or do not need fix_fields, too
+ */
+ new_cond->quick_fix_field();
+ new_cond->used_tables_cache= ((Item_cond_or*) cond)->used_tables_cache;
new_cond->top_level_item();
return new_cond;
}
@@ -7007,7 +7060,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
ref_key= -1;
/* Test if constant range in WHERE */
- if (tab->ref.key >= 0)
+ if (tab->ref.key >= 0 && tab->ref.key_parts)
{
ref_key= tab->ref.key;
ref_key_parts= tab->ref.key_parts;
@@ -7282,8 +7335,10 @@ static bool fix_having(JOIN *join, Item **having)
if (!table->select->cond)
table->select->cond=sort_table_cond;
else // This should never happen
- if (!(table->select->cond=new Item_cond_and(table->select->cond,
- sort_table_cond)))
+ if (!(table->select->cond= new Item_cond_and(table->select->cond,
+ sort_table_cond)) ||
+ table->select->cond->fix_fields(join->thd, join->tables_list,
+ &table->select->cond))
return 1;
table->select_cond=table->select->cond;
table->select_cond->top_level_item();
@@ -7902,10 +7957,16 @@ find_order_in_list(THD *thd, Item **ref_pointer_array,
}
order->in_field_list=0;
Item *it= *order->item;
- if (it->fix_fields(thd, tables, order->item) ||
- //'it' ressigned because fix_field can change it
- (it= *order->item)->check_cols(1) ||
- thd->is_fatal_error)
+ /*
+ We check it->fixed because Item_func_group_concat can put
+ arguments for which fix_fields already was called.
+
+ 'it' reassigned in if condition because fix_field can change it.
+ */
+ if (!it->fixed &&
+ (it->fix_fields(thd, tables, order->item) ||
+ (it= *order->item)->check_cols(1) ||
+ thd->is_fatal_error))
return 1; // Wrong field
uint el= all_fields.elements;
all_fields.push_front(it); // Add new field to field list
@@ -8731,7 +8792,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].
fieldnr-1];
Item *value=join_tab->ref.items[i];
- cond->add(new Item_func_equal(new Item_field(field),value));
+ cond->add(new Item_func_equal(new Item_field(field), value));
}
if (thd->is_fatal_error)
DBUG_RETURN(TRUE);
@@ -9315,7 +9376,7 @@ void st_select_lex::print(THD *thd, String *str)
str->append(table->db);
str->append('.');
str->append(table->real_name);
- if (strcmp(table->real_name, table->alias))
+ if (my_strcasecmp(table_alias_charset, table->real_name, table->alias))
{
str->append(' ');
str->append(table->alias);
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 36526bee066..fea3f7c6b80 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -432,4 +432,4 @@ bool cp_buffer_from_ref(TABLE_REF *ref);
bool error_if_full_join(JOIN *join);
int report_error(TABLE *table, int error);
int safe_index_read(JOIN_TAB *tab);
-COND *eliminate_not_funcs(COND *cond);
+COND *eliminate_not_funcs(THD *thd, COND *cond);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index c169ea8952f..d68db2cb3bc 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -921,7 +921,7 @@ mysqld_show_logs(THD *thd)
DBUG_RETURN(1);
#ifdef HAVE_BERKELEY_DB
- if (!berkeley_skip && berkeley_show_logs(protocol))
+ if ((have_berkeley_db == SHOW_OPTION_YES) && berkeley_show_logs(protocol))
DBUG_RETURN(-1);
#endif
@@ -1806,10 +1806,10 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
break;
case SHOW_SLAVE_RUNNING:
{
- LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&LOCK_active_mi);
end= strmov(buff, (active_mi->slave_running &&
active_mi->rli.slave_running) ? "ON" : "OFF");
- UNLOCK_ACTIVE_MI;
+ pthread_mutex_unlock(&LOCK_active_mi);
break;
}
#endif /* HAVE_REPLICATION */
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index c6eda5f9fb2..e15beac90b0 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -126,8 +126,8 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
- sprintf(buff,"%.14g",num); // Enough for a DATETIME
- return copy(buff, (uint32) strlen(buff), &my_charset_latin1, cs);
+ uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
+ return copy(buff, len, &my_charset_latin1, cs);
}
#ifdef HAVE_FCONVERT
int decpt,sign;
@@ -671,9 +671,8 @@ int String::reserve(uint32 space_needed, uint32 grow_by)
return FALSE;
}
-void String::qs_append(const char *str)
+void String::qs_append(const char *str, uint32 len)
{
- int len = strlen(str);
memcpy(Ptr + str_length, str, len + 1);
str_length += len;
}
@@ -681,8 +680,7 @@ void String::qs_append(const char *str)
void String::qs_append(double d)
{
char *buff = Ptr + str_length;
- sprintf(buff,"%.14g", d);
- str_length += strlen(buff);
+ str_length+= my_sprintf(buff, (buff, "%.14g", d));
}
void String::qs_append(double *d)
@@ -692,12 +690,6 @@ void String::qs_append(double *d)
qs_append(ld);
}
-void String::qs_append(const char &c)
-{
- Ptr[str_length] = c;
- str_length += sizeof(c);
-}
-
/*
Compare strings according to collation, without end space.
diff --git a/sql/sql_string.h b/sql/sql_string.h
index cdfb00276d4..32333b3b381 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -69,12 +69,10 @@ public:
Alloced_length=str.Alloced_length; alloced=0;
str_charset=str.str_charset;
}
- static void *operator new(size_t size)
- { return (void*) sql_alloc((uint) size); }
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr_arg,size_t size) /*lint -e715 */
- { sql_element_free(ptr_arg); }
+ {}
~String() { free(); }
inline void set_charset(CHARSET_INFO *charset) { str_charset= charset; }
@@ -237,7 +235,7 @@ public:
q_*** methods writes values of parameters itself
qs_*** methods writes string representation of value
*/
- void q_append(const char &c)
+ void q_append(const char c)
{
Ptr[str_length++] = c;
}
@@ -262,15 +260,19 @@ public:
str_length += data_len;
}
- void WriteAtPosition(int position, uint32 value)
+ void write_at_position(int position, uint32 value)
{
int4store(Ptr + position,value);
}
- void qs_append(const char *str);
+ void qs_append(const char *str, uint32 len);
void qs_append(double d);
void qs_append(double *d);
- void qs_append(const char &c);
+ inline void qs_append(const char c)
+ {
+ Ptr[str_length]= c;
+ str_length++;
+ }
/* Inline (general) functions used by the protocol functions */
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ee11b7b9da0..8011809d6ab 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -342,6 +342,47 @@ static int sort_keys(KEY *a, KEY *b)
0);
}
+/*
+ Check TYPELIB (set or enum) for duplicates
+
+ SYNOPSIS
+ check_duplicates_in_interval()
+ set_or_name "SET" or "ENUM" string for warning message
+ name name of the checked column
+ typelib list of values for the column
+
+ DESCRIPTION
+ This function prints an warning for each value in list
+ which has some duplicates on its right
+
+ RETURN VALUES
+ void
+*/
+
+void check_duplicates_in_interval(const char *set_or_name,
+ const char *name, TYPELIB *typelib)
+{
+ unsigned int old_count= typelib->count;
+ const char **old_type_names= typelib->type_names;
+
+ old_count= typelib->count;
+ old_type_names= typelib->type_names;
+ const char **cur_value= typelib->type_names;
+ for ( ; typelib->count > 1; cur_value++)
+ {
+ typelib->type_names++;
+ typelib->count--;
+ if (find_type((char*)*cur_value,typelib,1))
+ {
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_DUPLICATED_VALUE_IN_TYPE,
+ ER(ER_DUPLICATED_VALUE_IN_TYPE),
+ name,*cur_value,set_or_name);
+ }
+ }
+ typelib->count= old_count;
+ typelib->type_names= old_type_names;
+}
/*
Create a table
@@ -429,9 +470,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
sql_field->charset= create_info->default_table_charset;
/*
table_charset is set in ALTER TABLE if we want change character set
- for all varchar/char columns
+ for all varchar/char columns.
+ But the table charset must not affect the BLOB fields, so don't
+ allow to change my_charset_bin to somethig else.
*/
- if (create_info->table_charset)
+ if (create_info->table_charset && sql_field->charset != &my_charset_bin)
sql_field->charset= create_info->table_charset;
sql_field->create_length_to_internal_length();
@@ -546,6 +589,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::INTERVAL_FIELD;
+ check_duplicates_in_interval("ENUM",sql_field->field_name,
+ sql_field->interval);
break;
case FIELD_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
@@ -553,6 +598,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::BIT_FIELD;
+ check_duplicates_in_interval("SET",sql_field->field_name,
+ sql_field->interval);
break;
case FIELD_TYPE_DATE: // Rest of string types
case FIELD_TYPE_NEWDATE:
@@ -639,6 +686,12 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
key_parts+=key->columns.elements;
+ if (key->name && !tmp_table &&
+ !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
+ DBUG_RETURN(-1);
+ }
}
tmp=min(file->max_keys(), MAX_KEY);
if (key_count > tmp)
@@ -1079,7 +1132,8 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end)
{
char buff[MAX_FIELD_NAME],*buff_end;
- if (!check_if_keyname_exists(field_name,start,end))
+ if (!check_if_keyname_exists(field_name,start,end) &&
+ my_strcasecmp(system_charset_info,field_name,primary_key_name))
return (char*) field_name; // Use fieldname
buff_end=strmake(buff,field_name,MAX_FIELD_NAME-4);
for (uint i=2 ; ; i++)
@@ -2403,6 +2457,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (key->type != Key::FOREIGN_KEY)
key_list.push_back(key);
+ if (key->name &&
+ !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
+ DBUG_RETURN(-1);
+ }
}
}
@@ -2570,6 +2630,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
+
/*
Data is copied. Now we rename the old table to a temp name,
rename the new one to the old name, remove all entries from the old table
@@ -2918,12 +2979,10 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
/* calculating table's checksum */
ha_checksum crc= 0;
- if (t->db_type == DB_TYPE_INNODB) {
- /* InnoDB must be told explicitly to retrieve all columns, because
- this function does not set field->query_id in the columns to the
- current query id */
- t->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
- }
+ /* InnoDB must be told explicitly to retrieve all columns, because
+ this function does not set field->query_id in the columns to the
+ current query id */
+ t->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (t->file->rnd_init(1))
protocol->store_null();
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index a4461beed29..561f79f9de1 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -298,7 +298,11 @@ udf_func *find_udf(const char *name,uint length,bool mark_used)
DBUG_ENTER("find_udf");
/* TODO: This should be changed to reader locks someday! */
- rw_rdlock(&THR_LOCK_udf);
+ if (mark_used)
+ rw_wrlock(&THR_LOCK_udf); /* Called during fix_fields */
+ else
+ rw_rdlock(&THR_LOCK_udf); /* Called during parsing */
+
if ((udf=(udf_func*) hash_search(&udf_hash,(byte*) name,
length ? length : (uint) strlen(name))))
{
@@ -474,7 +478,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name->str,
(uint) udf_name->length)))
{
- net_printf(thd, ER_FUNCTION_NOT_DEFINED, udf_name);
+ net_printf(thd, ER_FUNCTION_NOT_DEFINED, udf_name->str);
goto err;
}
del_udf(udf);
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index a05fa44cfc9..87f70bcbd3a 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -203,6 +203,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
}
}
+ item_list.empty();
+ // it is not single select
if (first_select->next_select())
{
union_result->tmp_table_param.field_count= types.elements;
@@ -222,13 +224,13 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
result_table_list.table= table;
union_result->set_table(table);
- item_list.empty();
thd_arg->lex->current_select= lex_select_save;
{
Field **field;
for (field= table->field; *field; field++)
{
- if (item_list.push_back(new Item_field(*field)))
+ Item_field *item= new Item_field(*field);
+ if (!item || item_list.push_back(item))
DBUG_RETURN(-1);
}
}
@@ -458,4 +460,17 @@ int st_select_lex_unit::cleanup()
void st_select_lex_unit::reinit_exec_mechanism()
{
prepared= optimized= executed= 0;
+#ifndef DBUG_OFF
+ List_iterator_fast<Item> it(item_list);
+ Item_field *field;
+ while ((field= (Item_field *)it++))
+ {
+ /*
+ we can't cleanup here, because it broke link to temporary table field,
+ but have to drop fixed flag to allow next fix_field of this field
+ during re-executing
+ */
+ field->fixed= 0;
+ }
+#endif
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index f0491bc37d1..6242a03867b 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -261,6 +261,8 @@ int mysql_update(THD *thd,
}
}
}
+ if (thd->killed && !error)
+ error= 1; // Aborted
limit= tmp_limit;
end_read_record(&info);
/* Change select to use tempfile */
@@ -333,6 +335,8 @@ int mysql_update(THD *thd,
table->file->unlock_row();
thd->row_count++;
}
+ if (thd->killed && !error)
+ error= 1; // Aborted
end_read_record(&info);
free_io_cache(table); // If ORDER BY
thd->proc_info="end";
@@ -685,7 +689,7 @@ multi_update::initialize_tables(JOIN *join)
{
TABLE *table=table_ref->table;
uint cnt= table_ref->shared;
- Item_field *If;
+ Item_field *ifield;
List<Item> temp_fields= *fields_for_table[cnt];
ORDER group;
@@ -709,10 +713,10 @@ multi_update::initialize_tables(JOIN *join)
/* ok to be on stack as this is not referenced outside of this func */
Field_string offset(table->file->ref_length, 0, "offset",
table, &my_charset_bin);
- if (!(If=new Item_field(((Field *) &offset))))
+ if (!(ifield= new Item_field(((Field *) &offset))))
DBUG_RETURN(1);
- If->maybe_null=0;
- if (temp_fields.push_front(If))
+ ifield->maybe_null= 0;
+ if (temp_fields.push_front(ifield))
DBUG_RETURN(1);
/* Make an unique key over the first field to avoid duplicated updates */
@@ -937,14 +941,16 @@ int multi_update::do_updates(bool from_send_error)
DBUG_RETURN(0);
for (cur_table= update_tables; cur_table ; cur_table= cur_table->next)
{
+ byte *ref_pos;
+ TABLE *tmp_table;
+
table = cur_table->table;
if (table == table_to_update)
continue; // Already updated
-
org_updated= updated;
- byte *ref_pos;
- TABLE *tmp_table= tmp_tables[cur_table->shared];
+ tmp_table= tmp_tables[cur_table->shared];
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
+ (void) table->file->rnd_init(0);
table->file->extra(HA_EXTRA_NO_CACHE);
/*
@@ -1011,6 +1017,7 @@ int multi_update::do_updates(bool from_send_error)
else
trans_safe= 0; // Can't do safe rollback
}
+ (void) table->file->rnd_end();
}
DBUG_RETURN(0);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 4a098cc6fc0..1fc063a60ee 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -64,6 +64,7 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B)
Table_ident *table;
char *simple_string;
Item *item;
+ Item_num *item_num;
List<Item> *item_list;
List<String> *string_list;
String *string;
@@ -628,7 +629,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
using_list expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init geometry_function
- signed_literal NUM_literal
+ signed_literal
+
+%type <item_num>
+ NUM_literal
%type <item_list>
expr_list udf_expr_list when_list ident_list ident_list_arg
@@ -2508,7 +2512,7 @@ simple_expr:
$$= new Item_func_set_collation($1,
new Item_string($3.str,
$3.length,
- YYTHD->charset()));
+ YYTHD->charset()));
}
| literal
| param_marker
@@ -2524,6 +2528,12 @@ simple_expr:
}
| '@' '@' opt_var_ident_type ident_or_text opt_component
{
+
+ if ($4.str && $5.str && check_reserved_words(&$4))
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
if (!($$= get_system_var(YYTHD, (enum_var_type) $3, $4, $5)))
YYABORT;
}
@@ -2941,14 +2951,14 @@ geometry_function:
{ $$= GEOM_NEW(Item_func_geometry_from_wkb($3, $5)); }
| GEOMETRYCOLLECTION '(' expr_list ')'
{ $$= GEOM_NEW(Item_func_spatial_collection(* $3,
- Geometry::wkbGeometryCollection,
- Geometry::wkbPoint)); }
+ Geometry::wkb_geometrycollection,
+ Geometry::wkb_point)); }
| LINESTRING '(' expr_list ')'
{ $$= GEOM_NEW(Item_func_spatial_collection(* $3,
- Geometry::wkbLineString, Geometry::wkbPoint)); }
+ Geometry::wkb_linestring, Geometry::wkb_point)); }
| MULTILINESTRING '(' expr_list ')'
{ $$= GEOM_NEW( Item_func_spatial_collection(* $3,
- Geometry::wkbMultiLineString, Geometry::wkbLineString)); }
+ Geometry::wkb_multilinestring, Geometry::wkb_linestring)); }
| MLINEFROMTEXT '(' expr ')'
{ $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
| MLINEFROMTEXT '(' expr ',' expr ')'
@@ -2963,10 +2973,10 @@ geometry_function:
{ $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
| MULTIPOINT '(' expr_list ')'
{ $$= GEOM_NEW(Item_func_spatial_collection(* $3,
- Geometry::wkbMultiPoint, Geometry::wkbPoint)); }
+ Geometry::wkb_multipoint, Geometry::wkb_point)); }
| MULTIPOLYGON '(' expr_list ')'
{ $$= GEOM_NEW(Item_func_spatial_collection(* $3,
- Geometry::wkbMultiPolygon, Geometry::wkbPolygon)); }
+ Geometry::wkb_multipolygon, Geometry::wkb_polygon)); }
| POINT_SYM '(' expr ',' expr ')'
{ $$= GEOM_NEW(Item_func_point($3,$5)); }
| POINTFROMTEXT '(' expr ')'
@@ -2979,7 +2989,7 @@ geometry_function:
{ $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
| POLYGON '(' expr_list ')'
{ $$= GEOM_NEW(Item_func_spatial_collection(* $3,
- Geometry::wkbPolygon, Geometry::wkbLineString)); }
+ Geometry::wkb_polygon, Geometry::wkb_linestring)); }
| GEOMCOLLFROMTEXT '(' expr ')'
{ $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
| GEOMCOLLFROMTEXT '(' expr ',' expr ')'
@@ -3043,7 +3053,7 @@ opt_distinct:
|DISTINCT { $$ = 1; };
opt_gconcat_separator:
- /* empty */ { $$ = new String(",",1,default_charset_info); }
+ /* empty */ { $$ = new (&YYTHD->mem_root) String(",",1,default_charset_info); }
|SEPARATOR_SYM text_string { $$ = $2; };
@@ -3249,8 +3259,13 @@ select_derived:
YYABORT;
mysql_init_select(lex);
lex->current_select->linkage= DERIVED_TABLE_TYPE;
+ lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST;
}
- select_options select_item_list opt_select_from union_opt
+ select_options select_item_list
+ {
+ Select->parsing_place= SELECT_LEX_NODE::NO_MATTER;
+ }
+ opt_select_from union_opt
;
opt_outer:
@@ -3293,15 +3308,15 @@ key_list_or_empty:
key_usage_list2:
key_usage_list2 ',' ident
{ Select->
- interval_list.push_back(new String((const char*) $3.str, $3.length,
+ interval_list.push_back(new (&YYTHD->mem_root) String((const char*) $3.str, $3.length,
system_charset_info)); }
| ident
{ Select->
- interval_list.push_back(new String((const char*) $1.str, $1.length,
+ interval_list.push_back(new (&YYTHD->mem_root) String((const char*) $1.str, $1.length,
system_charset_info)); }
| PRIMARY_SYM
{ Select->
- interval_list.push_back(new String("PRIMARY", 7,
+ interval_list.push_back(new (&YYTHD->mem_root) String("PRIMARY", 7,
system_charset_info)); };
using_list:
@@ -4255,7 +4270,7 @@ opt_describe_column:
/* empty */ {}
| text_string { Lex->wild= $1; }
| ident
- { Lex->wild= new String((const char*) $1.str,$1.length,system_charset_info); };
+ { Lex->wild= new (&YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info); };
/* flush things */
@@ -4337,6 +4352,11 @@ purge_option:
YYABORT;
}
Item *tmp= new Item_func_unix_timestamp($2);
+ /*
+ it is OK only emulate fix_fieds, because we need only
+ value of constant
+ */
+ tmp->quick_fix_field();
Lex->sql_command = SQLCOM_PURGE_BEFORE;
Lex->purge_time= (ulong) tmp->val_int();
}
@@ -4467,22 +4487,34 @@ text_literal:
text_string:
TEXT_STRING_literal
- { $$= new String($1.str,$1.length,YYTHD->variables.collation_connection); }
+ { $$= new (&YYTHD->mem_root) String($1.str,$1.length,YYTHD->variables.collation_connection); }
| HEX_NUM
{
Item *tmp = new Item_varbinary($1.str,$1.length);
- $$= tmp ? tmp->val_str((String*) 0) : (String*) 0;
+ /*
+ it is OK only emulate fix_fieds, because we need only
+ value of constant
+ */
+ $$= tmp ?
+ tmp->quick_fix_field(), tmp->val_str((String*) 0) :
+ (String*) 0;
}
;
param_marker:
'?'
{
- LEX *lex=Lex;
- if (YYTHD->command == COM_PREPARE)
+ THD *thd=YYTHD;
+ LEX *lex= thd->lex;
+ if (thd->command == COM_PREPARE)
{
- lex->param_list.push_back($$=new Item_param((uint)(lex->tok_start-(uchar *)YYTHD->query)));
- lex->param_count++;
+ Item_param *item= new Item_param((uint) (lex->tok_start -
+ (uchar *) thd->query));
+ if (!($$= item) || lex->param_list.push_back(item))
+ {
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ YYABORT;
+ }
}
else
{
@@ -4495,7 +4527,11 @@ param_marker:
signed_literal:
literal { $$ = $1; }
| '+' NUM_literal { $$ = $2; }
- | '-' NUM_literal { $$ = new Item_func_neg($2); }
+ | '-' NUM_literal
+ {
+ $2->max_length++;
+ $$= $2->neg();
+ }
;
@@ -4508,7 +4544,13 @@ literal:
| UNDERSCORE_CHARSET HEX_NUM
{
Item *tmp= new Item_varbinary($2.str,$2.length);
- String *str= tmp ? tmp->val_str((String*) 0) : (String*) 0;
+ /*
+ it is OK only emulate fix_fieds, because we need only
+ value of constant
+ */
+ String *str= tmp ?
+ tmp->quick_fix_field(), tmp->val_str((String*) 0) :
+ (String*) 0;
$$= new Item_string(str ? str->ptr() : "",
str ? str->length() : 0,
Lex->charset);
@@ -5028,6 +5070,11 @@ internal_variable_name:
}
| ident '.' ident
{
+ if (check_reserved_words(&$1))
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
sys_var *tmp=find_sys_var($3.str, $3.length);
if (!tmp)
YYABORT;
@@ -5418,7 +5465,7 @@ column_list:
column_list_id:
ident
{
- String *new_str = new String((const char*) $1.str,$1.length,system_charset_info);
+ String *new_str = new (&YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
List_iterator <LEX_COLUMN> iter(Lex->columns);
class LEX_COLUMN *point;
LEX *lex=Lex;
diff --git a/sql/structs.h b/sql/structs.h
index 37208e63400..86d754f00d6 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -20,11 +20,21 @@
struct st_table;
class Field;
-typedef struct lex_string {
+typedef struct st_lex_string
+{
char *str;
uint length;
} LEX_STRING;
+typedef struct st_lex_string_with_init :public st_lex_string
+{
+ st_lex_string_with_init(const char *str_arg, uint length_arg)
+ {
+ str= (char*) str_arg;
+ length= length_arg;
+ }
+} LEX_STRING_WITH_INIT;
+
typedef struct st_date_time_format {
uchar positions[8];
@@ -210,7 +220,7 @@ typedef struct user_conn {
#define REG_NEW_RECORD 2 /* Write a new record if not found */
#define REG_UPDATE 4 /* Uppdate record */
#define REG_DELETE 8 /* Delete found record */
-#define REG_PROG 16 /* User is updateing database */
+#define REG_PROG 16 /* User is updating database */
#define REG_CLEAR_AFTER_WRITE 32
#define REG_MAY_BE_UPDATED 64
#define REG_AUTO_UPDATE 64 /* Used in D-forms for scroll-tables */
diff --git a/sql/table.cc b/sql/table.cc
index d9f832cf8bb..526810de74a 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -701,8 +701,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (db_stat)
{
int err;
+ unpack_filename(index_file,index_file);
if ((err=(outparam->file->
- ha_open(unpack_filename(index_file,index_file),
+ ha_open(index_file,
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
((db_stat & HA_WAIT_IF_LOCKED) ||
@@ -1283,7 +1284,9 @@ char *get_field(MEM_ROOT *mem, Field *field)
bool check_db_name(char *name)
{
- char *start=name;
+ char *start=name;
+ /* Used to catch empty names and names with end space */
+ bool last_char_is_space= TRUE;
if (lower_case_table_names)
my_casedn_str(files_charset_info, name);
@@ -1291,6 +1294,7 @@ bool check_db_name(char *name)
while (*name)
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
+ last_char_is_space= my_isspace(default_charset_info, *name);
if (use_mb(system_charset_info))
{
int len=my_ismbchar(system_charset_info, name,
@@ -1301,19 +1305,22 @@ bool check_db_name(char *name)
continue;
}
}
+#else
+ last_char_is_space= *name==' ';
#endif
if (*name == '/' || *name == '\\' || *name == FN_LIBCHAR ||
*name == FN_EXTCHAR)
return 1;
name++;
}
- return (uint) (name - start) > NAME_LEN || name == start;
+ return last_char_is_space || (uint) (name - start) > NAME_LEN;
}
/*
Allow anything as a table name, as long as it doesn't contain an
a '/', or a '.' character
+ or ' ' at the end
returns 1 on error
*/
@@ -1323,10 +1330,17 @@ bool check_table_name(const char *name, uint length)
const char *end= name+length;
if (!length || length > NAME_LEN)
return 1;
+#if defined(USE_MB) && defined(USE_MB_IDENT)
+ bool last_char_is_space= FALSE;
+#else
+ if (name[length-1]==' ')
+ return 1;
+#endif
while (name != end)
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
+ last_char_is_space= my_isspace(default_charset_info, *name);
if (use_mb(system_charset_info))
{
int len=my_ismbchar(system_charset_info, name, end);
@@ -1341,16 +1355,23 @@ bool check_table_name(const char *name, uint length)
return 1;
name++;
}
+#if defined(USE_MB) && defined(USE_MB_IDENT)
+ return last_char_is_space;
+#else
return 0;
+#endif
}
+
bool check_column_name(const char *name)
{
const char *start= name;
-
+ bool last_char_is_space= TRUE;
+
while (*name)
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
+ last_char_is_space= my_isspace(default_charset_info, *name);
if (use_mb(system_charset_info))
{
int len=my_ismbchar(system_charset_info, name,
@@ -1361,13 +1382,15 @@ bool check_column_name(const char *name)
continue;
}
}
+#else
+ last_char_is_space= *name==' ';
#endif
if (*name == NAMES_SEP_CHAR)
return 1;
name++;
}
/* Error if empty or too long column name */
- return (name == start || (uint) (name - start) > NAME_LEN);
+ return last_char_is_space || (uint) (name - start) > NAME_LEN;
}
/*
diff --git a/sql/time.cc b/sql/time.cc
index 1dff0c62edf..7fb466f6b97 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -391,9 +391,11 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
ulong not_zero_date, allow_space;
bool is_internal_format;
const char *pos, *last_field_pos;
+ const char *str_begin= str;
const char *end=str+length;
const uchar *format_position;
bool found_delimitier= 0, found_space= 0;
+ uint frac_pos, frac_len;
DBUG_ENTER("str_to_TIME");
DBUG_PRINT("ENTER",("str: %.*s",length,str));
@@ -482,7 +484,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0');
str++;
}
- date_len[i]+= (uint) (str - start);
+ date_len[i]= (uint) (str - start);
if (tmp_value > 999999) // Impossible date part
DBUG_RETURN(TIMESTAMP_NONE);
date[i]=tmp_value;
@@ -535,9 +537,9 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
{
if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
{
- if (str[1] == 'p' || str[1] == 'P')
+ if (str[0] == 'p' || str[0] == 'P')
add_hours= 12;
- else if (str[1] != 'a' || str[1] != 'A')
+ else if (str[0] != 'a' || str[0] != 'A')
continue; // Not AM/PM
str+= 2; // Skip AM/PM
/* Skip space after AM/PM */
@@ -555,7 +557,10 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
number_of_fields= i - start_loop;
while (i < MAX_DATE_PARTS)
- date[i++]=0;
+ {
+ date_len[i]= 0;
+ date[i++]= 0;
+ }
if (!is_internal_format)
{
@@ -569,7 +574,13 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
l_time->hour= date[(uint) format_position[3]];
l_time->minute= date[(uint) format_position[4]];
l_time->second= date[(uint) format_position[5]];
- l_time->second_part= date[(uint) format_position[6]];
+
+ frac_pos= (uint) format_position[6];
+ frac_len= date_len[frac_pos];
+ if (frac_len < 6)
+ date[frac_pos]*= (uint) log_10_int[6 - frac_len];
+ l_time->second_part= date[frac_pos];
+
if (format_position[7] != (uchar) 255)
{
if (l_time->hour > 12)
@@ -585,6 +596,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
l_time->hour= date[3];
l_time->minute= date[4];
l_time->second= date[5];
+ if (date_len[6] < 6)
+ date[6]*= (uint) log_10_int[6 - date_len[6]];
l_time->second_part=date[6];
}
l_time->neg= 0;
@@ -614,15 +627,17 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
current_thd->cuted_fields++;
goto err;
}
- if (str != end && current_thd->count_cuted_fields)
+
+ l_time->time_type= (number_of_fields <= 3 ?
+ TIMESTAMP_DATE : TIMESTAMP_DATETIME);
+
+ for (; str != end ; str++)
{
- for (; str != end ; str++)
+ if (!my_isspace(&my_charset_latin1,*str))
{
- if (!my_isspace(&my_charset_latin1,*str))
- {
- current_thd->cuted_fields++;
- break;
- }
+ make_truncated_value_warning(current_thd, str_begin, length,
+ l_time->time_type);
+ break;
}
}
@@ -686,6 +701,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
{
long date[5],value;
const char *end=str+length, *end_of_days;
+ const char *str_begin= str;
bool found_days,found_hours;
uint state;
@@ -706,7 +722,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
{ // Probably full timestamp
enum timestamp_type res= str_to_TIME(str,length,l_time,
(TIME_FUZZY_DATE |
- TIME_DATETIME_ONLY));
+ TIME_DATETIME_ONLY));
if ((int) res >= (int) TIMESTAMP_DATETIME_ERROR)
return res == TIMESTAMP_DATETIME_ERROR;
}
@@ -784,6 +800,8 @@ fractional:
my_isdigit(&my_charset_latin1,str[0]) &&
field_length--)
value=value*10 + (uint) (uchar) (*str - '0');
+ if (field_length)
+ value*= (long) log_10_int[field_length];
date[4]=value;
}
else
@@ -796,12 +814,12 @@ fractional:
str++;
if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
{
- if (str[1] == 'p' || str[1] == 'P')
+ if (str[0] == 'p' || str[0] == 'P')
{
str+= 2;
date[1]= date[1]%12 + 12;
}
- else if (str[1] == 'a' || str[1] == 'A')
+ else if (str[0] == 'a' || str[0] == 'A')
str+=2;
}
}
@@ -822,13 +840,14 @@ fractional:
l_time->time_type= TIMESTAMP_TIME;
/* Check if there is garbage at end of the TIME specification */
- if (str != end && current_thd->count_cuted_fields)
+ if (str != end)
{
do
{
if (!my_isspace(&my_charset_latin1,*str))
{
- current_thd->cuted_fields++;
+ make_truncated_value_warning(current_thd, str_begin, length,
+ TIMESTAMP_TIME);
break;
}
} while (++str != end);
@@ -1265,3 +1284,35 @@ void make_datetime(DATE_TIME_FORMAT *format, TIME *l_time, String *str)
str->length(length);
str->set_charset(&my_charset_bin);
}
+
+void make_truncated_value_warning(THD *thd, const char *str_val,
+ uint str_length, timestamp_type time_type)
+{
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ const char *type_str;
+
+ char buff[128];
+ String str(buff,(uint32) sizeof(buff), system_charset_info);
+ str.length(0);
+ str.append(str_val, str_length);
+ str.append('\0');
+
+ switch (time_type) {
+ case TIMESTAMP_DATE:
+ type_str= "date";
+ break;
+ case TIMESTAMP_DATETIME:
+ type_str= "datetime";
+ break;
+ case TIMESTAMP_TIME:
+ type_str= "time";
+ break;
+ default:
+ type_str= "string";
+ break;
+ }
+ sprintf(warn_buff, ER(ER_TRUNCATED_WRONG_VALUE),
+ type_str, str.ptr());
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TRUNCATED_WRONG_VALUE, warn_buff);
+}
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 712f909ae47..ee55cfda6c1 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -6284,7 +6284,8 @@ CHARSET_INFO my_charset_big5_chinese_ci=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_big5_handler,
&my_collation_big5_chinese_ci_handler
};
@@ -6308,7 +6309,8 @@ CHARSET_INFO my_charset_big5_bin=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_big5_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index ea7777aabc0..ea0a471ef74 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -388,7 +388,8 @@ CHARSET_INFO my_charset_bin =
1, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
- (char) 255, /* max_sort_char */
+ 0, /* min_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_8bit_bin_handler
};
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index 8aea7358a9c..ed8c0b5b415 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -634,7 +634,8 @@ CHARSET_INFO my_charset_latin2_czech_ci =
4, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_8bit_handler,
&my_collation_latin2_czech_ci_handler
};
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index ce6f695059f..7f89b8152e8 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -8692,7 +8692,8 @@ CHARSET_INFO my_charset_euckr_korean_ci=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -8716,7 +8717,8 @@ CHARSET_INFO my_charset_euckr_bin=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c
index 0085d264416..55dab3ca2a8 100644
--- a/strings/ctype-extra.c
+++ b/strings/ctype-extra.c
@@ -35,6 +35,7 @@ CHARSET_INFO compiled_charsets[] = {
0,
0,
0,
+ 0,
NULL,
NULL
}
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index 9f663f0b1ce..e5dfaf45276 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -5743,7 +5743,8 @@ CHARSET_INFO my_charset_gb2312_chinese_ci=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -5766,7 +5767,8 @@ CHARSET_INFO my_charset_gb2312_bin=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index f49bc5d360b..98511406ba9 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -9939,7 +9939,8 @@ CHARSET_INFO my_charset_gbk_chinese_ci=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -9962,7 +9963,8 @@ CHARSET_INFO my_charset_gbk_bin=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index eaef5441a65..0682b15d135 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -218,7 +218,8 @@ CHARSET_INFO my_charset_latin1=
1, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_8bit_simple_ci_handler
};
@@ -414,7 +415,8 @@ CHARSET_INFO my_charset_latin1_german2_ci=
2, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_german2_ci_handler
};
@@ -438,7 +440,8 @@ CHARSET_INFO my_charset_latin1_bin=
1, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_8bit_bin_handler
};
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 719ae14f653..0aae60a0b56 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -262,9 +262,9 @@ long my_strntol_8bit(CHARSET_INFO *cs,
{
if (c>='0' && c<='9')
c -= '0';
- else if (c>='A' && c<='F')
+ else if (c>='A' && c<='Z')
c = c - 'A' + 10;
- else if (c>='a' && c<='f')
+ else if (c>='a' && c<='z')
c = c - 'a' + 10;
else
break;
@@ -384,9 +384,9 @@ ulong my_strntoul_8bit(CHARSET_INFO *cs,
{
if (c>='0' && c<='9')
c -= '0';
- else if (c>='A' && c<='F')
+ else if (c>='A' && c<='Z')
c = c - 'A' + 10;
- else if (c>='a' && c<='f')
+ else if (c>='a' && c<='z')
c = c - 'a' + 10;
else
break;
@@ -499,9 +499,9 @@ longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)),
{
if (c>='0' && c<='9')
c -= '0';
- else if (c>='A' && c<='F')
+ else if (c>='A' && c<='Z')
c = c - 'A' + 10;
- else if (c>='a' && c<='f')
+ else if (c>='a' && c<='z')
c = c - 'a' + 10;
else
break;
@@ -622,9 +622,9 @@ ulonglong my_strntoull_8bit(CHARSET_INFO *cs,
{
if (c>='0' && c<='9')
c -= '0';
- else if (c>='A' && c<='F')
+ else if (c>='A' && c<='Z')
c = c - 'A' + 10;
- else if (c>='a' && c<='f')
+ else if (c>='a' && c<='z')
c = c - 'a' + 10;
else
break;
@@ -946,7 +946,7 @@ my_bool my_like_range_simple(CHARSET_INFO *cs,
if (*ptr == w_one) /* '_' in SQL */
{
*min_str++='\0'; /* This should be min char */
- *max_str++=cs->max_sort_char;
+ *max_str++= (char) cs->max_sort_char;
continue;
}
if (*ptr == w_many) /* '%' in SQL */
@@ -955,7 +955,7 @@ my_bool my_like_range_simple(CHARSET_INFO *cs,
*max_length=res_length;
do {
*min_str++ = ' '; /* Because if key compression */
- *max_str++ = cs->max_sort_char;
+ *max_str++ = (char) cs->max_sort_char;
} while (min_str != min_end);
return 0;
}
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index a4a8b3d4b2c..c337b8122fb 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -4528,7 +4528,8 @@ CHARSET_INFO my_charset_sjis_japanese_ci=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -4551,7 +4552,8 @@ CHARSET_INFO my_charset_sjis_bin=
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index abe9972cfd6..59be820863a 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -913,7 +913,8 @@ CHARSET_INFO my_charset_tis620_thai_ci=
4, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -936,7 +937,8 @@ CHARSET_INFO my_charset_tis620_bin=
1, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_8bit_bin_handler
};
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 908d27859ff..f4c1a22939a 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -1284,13 +1284,94 @@ void my_hash_sort_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)),
}
}
+/*
+** Calculate min_str and max_str that ranges a LIKE string.
+** Arguments:
+** ptr Pointer to LIKE string.
+** ptr_length Length of LIKE string.
+** escape Escape character in LIKE. (Normally '\').
+** All escape characters should be removed from min_str and max_str
+** res_length Length of min_str and max_str.
+** min_str Smallest case sensitive string that ranges LIKE.
+** Should be space padded to res_length.
+** max_str Largest case sensitive string that ranges LIKE.
+** Normally padded with the biggest character sort value.
+**
+** The function should return 0 if ok and 1 if the LIKE string can't be
+** optimized !
+*/
+
+my_bool my_like_range_ucs2(CHARSET_INFO *cs,
+ const char *ptr,uint ptr_length,
+ pbool escape, pbool w_one, pbool w_many,
+ uint res_length,
+ char *min_str,char *max_str,
+ uint *min_length,uint *max_length)
+{
+ const char *end=ptr+ptr_length;
+ char *min_org=min_str;
+ char *min_end=min_str+res_length;
+
+ for (; ptr + 1 < end && min_str + 1 < min_end ; ptr+=2)
+ {
+ if (ptr[0] == '\0' && ptr[1] == escape && ptr+2 < end)
+ {
+ ptr+=2; /* Skip escape */
+ *min_str++= *max_str++ = ptr[0];
+ *min_str++= *max_str++ = ptr[1];
+ continue;
+ }
+ if (ptr[0] == '\0' && ptr[1] == w_one) /* '_' in SQL */
+ {
+ *min_str++= (char) cs->min_sort_char >> 8;
+ *min_str++= (char) cs->min_sort_char & 255;
+ *max_str++= (char) cs->max_sort_char >> 8;
+ *max_str++= (char) cs->max_sort_char & 255;
+ continue;
+ }
+ if (ptr[0] == '\0' && ptr[1] == w_many) /* '%' in SQL */
+ {
+ *min_length= (uint) (min_str - min_org);
+ *max_length=res_length;
+ do {
+ *min_str++ = '\0';
+ *min_str++ = ' '; /* Because if key compression */
+ *max_str++ = (char) cs->max_sort_char >>8;
+ *max_str++ = (char) cs->max_sort_char & 255;
+ } while (min_str + 1 < min_end);
+ return 0;
+ }
+ *min_str++= *max_str++ = ptr[0];
+ *min_str++= *max_str++ = ptr[1];
+ }
+ *min_length= *max_length = (uint) (min_str - min_org);
+
+ /* Temporary fix for handling w_one at end of string (key compression) */
+ {
+ char *tmp;
+ for (tmp= min_str ; tmp-1 > min_org && tmp[-1] == '\0' && tmp[-2]=='\0';)
+ {
+ *--tmp=' ';
+ *--tmp='\0';
+ }
+ }
+
+ while (min_str + 1 < min_end)
+ {
+ *min_str++ = *max_str++ = '\0';
+ *min_str++ = *max_str++ = ' '; /* Because if key compression */
+ }
+ return 0;
+}
+
+extern MY_COLLATION_HANDLER my_collation_uca_handler;
static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler =
{
my_strnncoll_ucs2,
my_strnncoll_ucs2,
my_strnxfrm_ucs2,
- my_like_range_simple,
+ my_like_range_ucs2,
my_wildcmp_ucs2_ci,
my_strcasecmp_ucs2,
my_instr_mb,
@@ -1356,7 +1437,8 @@ CHARSET_INFO my_charset_ucs2_general_ci=
1, /* strxfrm_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
&my_charset_ucs2_handler,
&my_collation_ucs2_general_ci_handler
};
@@ -1380,7 +1462,8 @@ CHARSET_INFO my_charset_ucs2_bin=
1, /* strxfrm_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
&my_charset_ucs2_handler,
&my_collation_ucs2_bin_handler
};
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index acb1d049a03..997618d7645 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -8483,7 +8483,8 @@ CHARSET_INFO my_charset_ujis_japanese_ci=
1, /* strxfrm_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -8506,7 +8507,8 @@ CHARSET_INFO my_charset_ujis_bin=
1, /* strxfrm_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index cafc43f3f70..dca73e5a79f 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -2009,7 +2009,8 @@ CHARSET_INFO my_charset_utf8_general_ci=
1, /* strxfrm_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -2033,7 +2034,8 @@ CHARSET_INFO my_charset_utf8_bin=
1, /* strxfrm_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index 889cf2d2dae..bda349f1988 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -629,7 +629,8 @@ CHARSET_INFO my_charset_cp1250_czech_ci =
2, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
- 0,
+ 0, /* min_sort_char */
+ 0, /* max_sort_char */
&my_charset_8bit_handler,
&my_collation_czech_ci_handler
};
diff --git a/strings/strtod.c b/strings/strtod.c
index 027abe56269..bc8105b8040 100644
--- a/strings/strtod.c
+++ b/strings/strtod.c
@@ -2,7 +2,7 @@
An alternative implementation of "strtod()" that is both
simplier, and thread-safe.
- From mit-threads as bundled with MySQL 3.22
+ From mit-threads as bundled with MySQL 3.23
SQL:2003 specifies a number as
@@ -26,7 +26,7 @@
*/
-#include "my_base.h"
+#include "my_base.h" /* Includes errno.h */
#include "m_ctype.h"
static double scaler10[] = {
@@ -36,11 +36,13 @@ static double scaler1[] = {
1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9
};
+
double my_strtod(const char *str, char **end)
{
double result= 0.0;
int negative, ndigits;
const char *old_str;
+ my_bool overflow=0;
while (my_isspace(&my_charset_latin1, *str))
str++;
@@ -85,15 +87,16 @@ double my_strtod(const char *str, char **end)
double scaler= 1.0;
while (my_isdigit (&my_charset_latin1, *str))
{
- exp= exp*10 + *str - '0';
+ if (exp < 9999) /* protection against exp overflow */
+ exp= exp*10 + *str - '0';
str++;
}
if (exp >= 1000)
{
- if (neg)
- result= 0.0;
- else
- result= DBL_MAX;
+ if (neg)
+ result= 0.0;
+ else
+ overflow= 1;
goto done;
}
while (exp >= 100)
@@ -113,8 +116,11 @@ done:
if (end)
*end = (char *)str;
- if (isinf(result))
- result=DBL_MAX;
+ if (overflow || isinf(result))
+ {
+ result= DBL_MAX;
+ errno= EOVERFLOW;
+ }
return negative ? -result : result;
}
diff --git a/strings/uca-dump.c b/strings/uca-dump.c
new file mode 100644
index 00000000000..c8339d7b85b
--- /dev/null
+++ b/strings/uca-dump.c
@@ -0,0 +1,258 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef unsigned char uchar;
+typedef unsigned short uint16;
+
+struct uca_item_st
+{
+ uchar num;
+ uint16 weight[4][8];
+};
+
+#if 1
+#define MY_UCA_NPAGES 1024
+#define MY_UCA_NCHARS 64
+#define MY_UCA_CMASK 63
+#define MY_UCA_PSHIFT 6
+#else
+#define MY_UCA_NPAGES 256
+#define MY_UCA_NCHARS 256
+#define MY_UCA_CMASK 255
+#define MY_UCA_PSHIFT 8
+#endif
+
+int main(int ac, char **av)
+{
+ char str[256];
+ char *weights[64];
+ struct uca_item_st uca[64*1024];
+ size_t code, page, w;
+ int pagemaxlen[MY_UCA_NPAGES];
+
+ bzero(uca, sizeof(uca));
+
+ while (fgets(str,sizeof(str),stdin))
+ {
+ char *comment;
+ char *weight;
+ char *s;
+ size_t codenum;
+
+ code= strtol(str,NULL,16);
+
+ if (str[0]=='#' || (code > 0xFFFF))
+ continue;
+ if ((comment=strchr(str,'#')))
+ {
+ *comment++= '\0';
+ for ( ; *comment==' ' ; comment++);
+ }else
+ continue;
+
+ if ((weight=strchr(str,';')))
+ {
+ *weight++= '\0';
+ for ( ; *weight==' ' ; weight++);
+ }
+ else
+ continue;
+
+ codenum= 0;
+ s= strtok(str, " \t");
+ while (s)
+ {
+ s= strtok(NULL, " \t");
+ codenum++;
+ }
+
+ if (codenum>1)
+ {
+ /* Multi-character weight */
+ continue;
+ }
+
+ uca[code].num= 0;
+ s= strtok(weight, " []");
+ while (s)
+ {
+ weights[uca[code].num]= s;
+ s= strtok(NULL, " []");
+ uca[code].num++;
+ }
+
+ for (w=0; w < uca[code].num; w++)
+ {
+ size_t partnum;
+
+ partnum= 0;
+ s= weights[w];
+ while (*s)
+ {
+ char *endptr;
+ size_t part;
+ part= strtol(s+1,&endptr,16);
+ uca[code].weight[partnum][w]= part;
+ s= endptr;
+ partnum++;
+ }
+
+ }
+ }
+
+ /* Now set implicit weights */
+ for (code=0; code <= 0xFFFF; code++)
+ {
+ size_t base, aaaa, bbbb;
+
+ if (uca[code].num)
+ continue;
+
+ /*
+ 3400;<CJK Ideograph Extension A, First>
+ 4DB5;<CJK Ideograph Extension A, Last>
+ 4E00;<CJK Ideograph, First>
+ 9FA5;<CJK Ideograph, Last>
+ */
+
+ if (code >= 0x3400 && code <= 0x4DB5)
+ base= 0xFB80;
+ else if (code >= 0x4E00 && code <= 0x9FA5)
+ base= 0xFB40;
+ else
+ base= 0xFBC0;
+
+ aaaa= base + (code >> 15);
+ bbbb= (code & 0x7FFF) | 0x8000;
+ uca[code].weight[0][0]= aaaa;
+ uca[code].weight[0][1]= bbbb;
+
+ uca[code].weight[1][0]= 0x0020;
+ uca[code].weight[1][1]= 0x0000;
+
+ uca[code].weight[2][0]= 0x0002;
+ uca[code].weight[2][1]= 0x0000;
+
+ uca[code].weight[3][0]= 0x0001;
+ uca[code].weight[3][2]= 0x0000;
+
+ uca[code].num= 2;
+ }
+
+ printf("#include \"my_uca.h\"\n");
+
+ printf("#define MY_UCA_NPAGES %d\n",MY_UCA_NPAGES);
+ printf("#define MY_UCA_NCHARS %d\n",MY_UCA_NCHARS);
+ printf("#define MY_UCA_CMASK %d\n",MY_UCA_CMASK);
+ printf("#define MY_UCA_PSHIFT %d\n",MY_UCA_PSHIFT);
+
+ for (w=0; w<1; w++)
+ {
+ for (page=0; page < MY_UCA_NPAGES; page++)
+ {
+ size_t offs;
+ size_t maxnum= 0;
+ size_t nchars= 0;
+ size_t mchars;
+
+
+ /*
+ Calculate maximum weight
+ length for this page
+ */
+
+ for (offs=0; offs < MY_UCA_NCHARS; offs++)
+ {
+ size_t i, num;
+
+ code= page*MY_UCA_NCHARS+offs;
+
+ /* Calculate only non-zero weights */
+ num=0;
+ for (i=0; i < uca[code].num; i++)
+ if (uca[code].weight[w][i])
+ num++;
+
+ maxnum= maxnum < num ? num : maxnum;
+ }
+ if (!maxnum)
+ maxnum=1;
+
+ switch (maxnum)
+ {
+ case 0: mchars= 8; break;
+ case 1: mchars= 8; break;
+ case 2: mchars= 8; break;
+ case 3: mchars= 9; break;
+ case 4: mchars= 8; break;
+ default: mchars= uca[code].num;
+ }
+
+ pagemaxlen[page]= maxnum;
+
+ printf("uint16 page%03Xdata[]= { /* %04X (%d weights per char) */\n",
+ page, page*MY_UCA_NCHARS, maxnum);
+
+ /*
+ Now print this page
+ */
+
+ for (offs=0; offs < MY_UCA_NCHARS; offs++)
+ {
+ uint16 weight[8];
+ size_t num, i;
+
+ code= page*MY_UCA_NCHARS+offs;
+
+ bzero(weight,sizeof(weight));
+
+ /* Copy non-zero weights */
+ for (num=0, i=0; i < uca[code].num; i++)
+ {
+ if (uca[code].weight[w][i])
+ {
+ weight[num]= uca[code].weight[w][i];
+ num++;
+ }
+ }
+
+ for (i=0; i < maxnum; i++)
+ {
+ printf("0x%04X",(int)weight[i]);
+ if ((offs+1 != MY_UCA_NCHARS) || (i+1!=maxnum))
+ printf(",");
+ nchars++;
+ }
+ if (nchars >=mchars)
+ {
+ printf("\n");
+ nchars=0;
+ }
+ else
+ {
+ printf(" ");
+ }
+ }
+ printf("};\n\n");
+ }
+ }
+
+ printf("uchar ucal[%d]={\n",MY_UCA_NPAGES);
+ for (page=0; page < MY_UCA_NPAGES; page++)
+ {
+ printf("%d%s%s",pagemaxlen[page],page<MY_UCA_NPAGES-1?",":"",(page+1) % 16 ? "":"\n");
+ }
+ printf("};\n");
+
+
+ printf("uint16 *ucaw[%d]={\n",MY_UCA_NPAGES);
+ for (page=0; page < MY_UCA_NPAGES; page++)
+ {
+ printf("page%03Xdata%s%s",page,page<MY_UCA_NPAGES-1?",":"", (page+1) % 4 ? "":"\n");
+ }
+ printf("};\n");
+
+ printf("int main(void){ return 0;};\n");
+ return 0;
+}
diff --git a/support-files/Makefile.am b/support-files/Makefile.am
index 58808b5e255..196da3d8744 100644
--- a/support-files/Makefile.am
+++ b/support-files/Makefile.am
@@ -35,6 +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
diff --git a/support-files/my-innodb-heavy-4G.cnf.sh b/support-files/my-innodb-heavy-4G.cnf.sh
index 9c772269749..54df6a8bfe6 100644
--- a/support-files/my-innodb-heavy-4G.cnf.sh
+++ b/support-files/my-innodb-heavy-4G.cnf.sh
@@ -71,7 +71,7 @@ max_connections = 100
# the host will be blocked from connecting to the MySQL server until
# "FLUSH HOSTS" has been run or the server was restarted. Invalid
# passwords and other errors during the connect phase result in
-# increasing this value. See the "Aborted_Connects" status variable for
+# increasing this value. See the "Aborted_connects" status variable for
# global counter.
max_connect_errors = 10
@@ -111,14 +111,14 @@ max_heap_table_size = 64M
# Sort buffer is used to perform sorts for some ORDER BY and GROUP BY
# queries. If sorted data does not fit into the sort buffer, a disk
-# based merge sort is used instead - See "sort_merge_passes". Allocated
-# per thread if sort is needed.
+# based merge sort is used instead - See the "Sort_merge_passes"
+# status variable. Allocated per thread if sort is needed.
sort_buffer_size = 8M
# This buffer is used for the optimization of full JOINs (JOINs without
# indexes). Such JOINs are very bad for performance in most cases
# anyway, but setting this variable to a large value reduces the
-# performance impact. See the "select_full_join" status variable for a
+# performance impact. See the "Select_full_join" status variable for a
# count of full JOINs. Allocated per thread if full join is found
join_buffer_size = 8M
diff --git a/tests/client_test.c b/tests/client_test.c
index 3b9aefc6ec2..31a53f6d81e 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -2963,6 +2963,8 @@ static void test_bind_result_ext()
fprintf(stdout, "\n data (double) : %f", d_data);
fprintf(stdout, "\n data (str) : %s(%lu)", szData, szLength);
+
+ bData[bLength]= '\0'; /* bData is binary */
fprintf(stdout, "\n data (bin) : %s(%lu)", bData, bLength);
@@ -3939,6 +3941,7 @@ static void test_prepare_resultset()
result = mysql_get_metadata(stmt);
mytest(result);
my_print_result_metadata(result);
+ mysql_free_result(result);
mysql_stmt_close(stmt);
}
@@ -4070,18 +4073,18 @@ static void test_stmt_close()
fprintf(stdout,"\n mysql_close_stmt(1) returned: %d", rc);
assert(rc == 0);
- mysql_close(lmysql); /* it should free all open stmts(stmt3, 2 and 1) */
+ /*
+ Originally we were going to close all statements automatically in
+ mysql_close(). This proved to not work well - users weren't able to
+ close statements by hand once mysql_close() had been called.
+ Now mysql_close() doesn't free any statements, so this test doesn't
+ serve its original destination any more.
+ Here we free stmt2 and stmt3 by hande to avoid memory leaks.
+ */
+ mysql_stmt_close(stmt2);
+ mysql_stmt_close(stmt3);
+ mysql_close(lmysql);
-#if NOT_VALID
- rc= mysql_stmt_close(stmt3);
- fprintf(stdout,"\n mysql_close_stmt(3) returned: %d", rc);
- assert( rc == 1);
-
- rc= mysql_stmt_close(stmt2);
- fprintf(stdout,"\n mysql_close_stmt(2) returned: %d", rc);
- assert( rc == 1);
-#endif
-
count= 100;
bind[0].buffer=(char *)&count;
bind[0].buffer_type=MYSQL_TYPE_LONG;
@@ -4871,7 +4874,10 @@ DROP TABLE IF EXISTS test_multi_tab";
{
fprintf(stdout,"\n Query %d: ", count);
if ((result= mysql_store_result(mysql_local)))
+ {
my_process_result_set(result);
+ mysql_free_result(result);
+ }
else
fprintf(stdout,"OK, %lld row(s) affected, %d warning(s)\n",
mysql_affected_rows(mysql_local),
@@ -5768,6 +5774,7 @@ static void test_open_direct()
mytest(result);
assert(0 == my_process_result_set(result));
+ mysql_free_result(result);
rc = mysql_execute(stmt);
mystmt(stmt, rc);
@@ -5781,6 +5788,7 @@ static void test_open_direct()
mytest(result);
assert(1 == my_process_result_set(result));
+ mysql_free_result(result);
rc = mysql_execute(stmt);
mystmt(stmt, rc);
@@ -5794,6 +5802,8 @@ static void test_open_direct()
mytest(result);
assert(2 == my_process_result_set(result));
+ mysql_free_result(result);
+
mysql_stmt_close(stmt);
/* run a direct query in the middle of a fetch */
@@ -6446,6 +6456,7 @@ static void test_prepare_grant()
assert(4 == my_stmt_result("SELECT * FROM test_grant"));
+ mysql_stmt_close(stmt);
mysql_close(lmysql);
mysql= org_mysql;
@@ -7552,6 +7563,8 @@ static void test_mem_overun()
rc = mysql_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
+ mysql_free_result(field_res);
+
mysql_stmt_close(stmt);
}
@@ -7876,6 +7889,7 @@ static void test_ts()
ts.hour= 21;
ts.minute= 07;
ts.second= 46;
+ ts.second_part= 0;
length= (long)(strmov(strts,"2003-07-12 21:07:46") - strts);
bind[0].buffer_type= MYSQL_TYPE_TIMESTAMP;
@@ -7984,6 +7998,8 @@ static void test_bug1500()
bind[0].buffer= (char *)int_data;
bind[0].buffer_type= FIELD_TYPE_LONG;
bind[0].is_null= 0;
+ bind[0].length= NULL;
+ bind[0].buffer_length= 0;
bind[2]= bind[1]= bind[0];
bind[1].buffer= (char *)(int_data + 1);
bind[2].buffer= (char *)(int_data + 2);
@@ -8190,7 +8206,6 @@ static void test_bug2247()
}
-
static void test_subqueries()
{
MYSQL_STMT *stmt;
@@ -8330,6 +8345,37 @@ static void test_bug2248()
myquery(rc);
}
+static void test_subqueries_ref()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query= "SELECT a as ccc from t1 where a+1=(SELECT 1+ccc from t1 where ccc+1=a+1 and a=1)";
+
+ myheader("test_subquery_ref");
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"CREATE TABLE t1 (a int);");
+ myquery(rc);
+
+ rc= mysql_query(mysql,
+ "insert into t1 values (1), (2), (3), (4), (5);");
+ myquery(rc);
+
+ stmt= mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_execute(stmt);
+ mystmt(stmt, rc);
+ assert(1 == my_process_stmt_result(stmt));
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+}
/*
Read and parse arguments and MySQL options from my.cnf
@@ -8422,9 +8468,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
static void get_options(int argc, char **argv)
{
int ho_error;
- load_defaults("my",client_test_load_default_groups,&argc,&argv);
- if ((ho_error= handle_options(&argc,&argv, client_test_long_options,
+ if ((ho_error= handle_options(&argc, &argv, client_test_long_options,
get_one_option)))
exit(ho_error);
@@ -8454,6 +8499,7 @@ static void print_test_output()
*********************************************************/
int main(int argc, char **argv)
{
+ DEBUGGER_OFF;
MY_INIT(argv[0]);
load_defaults("my",client_test_load_default_groups,&argc,&argv);
@@ -8470,8 +8516,6 @@ int main(int argc, char **argv)
start_time= time((time_t *)0);
- test_subqueries();
-
client_query(); /* simple client query test */
#if NOT_YET_WORKING
/* Used for internal new development debugging */
@@ -8588,6 +8632,9 @@ int main(int argc, char **argv)
test_subqueries(); /* repeatable subqueries */
test_bad_union(); /* correct setup of UNION */
test_distinct(); /* distinct aggregate functions */
+ test_subqueries_ref(); /* outer reference in subqueries converted
+ Item_field -> Item_ref */
+
end_time= time((time_t *)0);
@@ -8599,6 +8646,7 @@ int main(int argc, char **argv)
client_disconnect(); /* disconnect from server */
free_defaults(defaults_argv);
print_test_output();
-
+ my_end(0);
+
return(0);
}
diff --git a/tests/thread_test.c b/tests/thread_test.c
index c201cbb9b83..06f335fe1a6 100644
--- a/tests/thread_test.c
+++ b/tests/thread_test.c
@@ -104,7 +104,7 @@ static struct my_option my_long_options[] =
{"query", 'Q', "Query to execute in each threads", (gptr*) &query,
(gptr*) &query, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection", (gptr*) &tcp_port,
- (gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0},
{"socket", 'S', "Socket file to use for connection", (gptr*) &unix_socket,
(gptr*) &unix_socket, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"test-count", 'c', "Run test count times (default %d)",