summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarty@linux.site <>2005-06-30 12:20:52 +0200
committermarty@linux.site <>2005-06-30 12:20:52 +0200
commite4aedcc2c137ba667e3d429031ce284032e11060 (patch)
treed61554cba3c2aa34bee31d02127690c317681d2a
parent5e4ce743a351f7d1ee55b534dd689e2d082fa146 (diff)
parent2eea2f52089028e97ab1c3b9e33e68fd8eadb094 (diff)
downloadmariadb-git-e4aedcc2c137ba667e3d429031ce284032e11060.tar.gz
Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.0-ndb
into linux.site:/home/marty/MySQL/mysql-5.0
-rw-r--r--.bzrignore1
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--Docs/Makefile.am10
-rwxr-xr-xDocs/Support/generate-flag-images31
-rwxr-xr-xDocs/Support/generate-text-files.pl2
-rw-r--r--Makefile.am3
-rw-r--r--VC++Files/libmysql/libmysql.dsp4
-rw-r--r--client/Makefile.am14
-rw-r--r--client/mysql.cc3
-rw-r--r--client/mysqldump.c231
-rw-r--r--client/mysqltest.c117
-rw-r--r--config/ac-macros/misc.m456
-rw-r--r--config/ac-macros/yassl.m41
-rw-r--r--configure.in31
-rw-r--r--extra/yassl/include/lock.hpp6
-rw-r--r--extra/yassl/include/socket_wrapper.hpp4
-rw-r--r--extra/yassl/include/yassl_int.hpp7
-rw-r--r--extra/yassl/include/yassl_types.hpp11
-rw-r--r--extra/yassl/mySTL/helpers.hpp23
-rw-r--r--extra/yassl/src/crypto_wrapper.cpp4
-rw-r--r--extra/yassl/src/lock.cpp6
-rw-r--r--extra/yassl/src/log.cpp4
-rw-r--r--extra/yassl/src/socket_wrapper.cpp16
-rw-r--r--extra/yassl/src/ssl.cpp2
-rw-r--r--extra/yassl/src/template_instnt.cpp42
-rw-r--r--extra/yassl/src/timer.cpp6
-rw-r--r--extra/yassl/src/yassl_int.cpp9
-rw-r--r--extra/yassl/taocrypt/include/misc.hpp11
-rw-r--r--extra/yassl/taocrypt/include/random.hpp2
-rw-r--r--extra/yassl/taocrypt/include/runtime.hpp4
-rw-r--r--extra/yassl/taocrypt/include/types.hpp20
-rw-r--r--extra/yassl/taocrypt/src/algebra.cpp2
-rw-r--r--extra/yassl/taocrypt/src/asn.cpp1
-rw-r--r--extra/yassl/taocrypt/src/dh.cpp1
-rw-r--r--extra/yassl/taocrypt/src/dsa.cpp1
-rw-r--r--extra/yassl/taocrypt/src/integer.cpp43
-rw-r--r--extra/yassl/taocrypt/src/misc.cpp16
-rw-r--r--extra/yassl/taocrypt/src/random.cpp10
-rw-r--r--extra/yassl/taocrypt/src/rsa.cpp1
-rw-r--r--extra/yassl/taocrypt/src/template_instnt.cpp2
-rw-r--r--heap/hp_hash.c8
-rw-r--r--heap/hp_update.c2
-rw-r--r--include/config-netware.h10
-rw-r--r--include/my_base.h1
-rw-r--r--include/my_global.h2
-rw-r--r--include/mysql_com.h4
-rw-r--r--innobase/btr/btr0btr.c174
-rw-r--r--innobase/btr/btr0cur.c255
-rw-r--r--innobase/btr/btr0pcur.c66
-rw-r--r--innobase/btr/btr0sea.c191
-rw-r--r--innobase/buf/buf0buf.c40
-rw-r--r--innobase/buf/buf0flu.c6
-rw-r--r--innobase/buf/buf0lru.c6
-rw-r--r--innobase/buf/buf0rea.c8
-rw-r--r--innobase/configure.in7
-rw-r--r--innobase/data/data0data.c2
-rw-r--r--innobase/data/data0type.c4
-rw-r--r--innobase/dict/dict0boot.c9
-rw-r--r--innobase/dict/dict0crea.c2
-rw-r--r--innobase/dict/dict0dict.c23
-rw-r--r--innobase/dict/dict0mem.c1
-rw-r--r--innobase/fil/fil0fil.c29
-rw-r--r--innobase/fsp/fsp0fsp.c4
-rw-r--r--innobase/ibuf/ibuf0ibuf.c54
-rw-r--r--innobase/include/btr0btr.h11
-rw-r--r--innobase/include/btr0btr.ic4
-rw-r--r--innobase/include/btr0cur.h2
-rw-r--r--innobase/include/btr0cur.ic4
-rw-r--r--innobase/include/buf0buf.h20
-rw-r--r--innobase/include/buf0buf.ic29
-rw-r--r--innobase/include/buf0lru.h2
-rw-r--r--innobase/include/data0type.h2
-rw-r--r--innobase/include/data0type.ic4
-rw-r--r--innobase/include/dyn0dyn.h2
-rw-r--r--innobase/include/dyn0dyn.ic7
-rw-r--r--innobase/include/lock0lock.h19
-rw-r--r--innobase/include/log0log.h4
-rw-r--r--innobase/include/mach0data.h21
-rw-r--r--innobase/include/mach0data.ic31
-rw-r--r--innobase/include/mem0mem.ic2
-rw-r--r--innobase/include/mtr0log.h14
-rw-r--r--innobase/include/mtr0mtr.h6
-rw-r--r--innobase/include/os0file.h15
-rw-r--r--innobase/include/page0cur.h8
-rw-r--r--innobase/include/page0cur.ic22
-rw-r--r--innobase/include/page0page.h68
-rw-r--r--innobase/include/page0page.ic270
-rw-r--r--innobase/include/read0read.ic9
-rw-r--r--innobase/include/rem0rec.h59
-rw-r--r--innobase/include/rem0rec.ic122
-rw-r--r--innobase/include/row0mysql.h17
-rw-r--r--innobase/include/row0sel.ic2
-rw-r--r--innobase/include/row0upd.ic2
-rw-r--r--innobase/include/sync0rw.ic39
-rw-r--r--innobase/include/trx0rseg.ic4
-rw-r--r--innobase/include/trx0trx.h20
-rw-r--r--innobase/include/univ.i26
-rw-r--r--innobase/include/ut0dbg.h119
-rw-r--r--innobase/include/ut0rnd.ic6
-rw-r--r--innobase/lock/lock0lock.c344
-rw-r--r--innobase/log/log0log.c60
-rw-r--r--innobase/log/log0recv.c65
-rw-r--r--innobase/mtr/mtr0log.c24
-rw-r--r--innobase/mtr/mtr0mtr.c12
-rw-r--r--innobase/os/os0file.c89
-rw-r--r--innobase/page/page0cur.c56
-rw-r--r--innobase/page/page0page.c151
-rw-r--r--innobase/pars/lexyy.c5
-rw-r--r--innobase/pars/pars0lex.l3
-rw-r--r--innobase/rem/rem0cmp.c99
-rw-r--r--innobase/rem/rem0rec.c145
-rw-r--r--innobase/row/row0ins.c116
-rw-r--r--innobase/row/row0mysql.c55
-rw-r--r--innobase/row/row0purge.c4
-rw-r--r--innobase/row/row0row.c10
-rw-r--r--innobase/row/row0sel.c373
-rw-r--r--innobase/row/row0umod.c15
-rw-r--r--innobase/row/row0undo.c2
-rw-r--r--innobase/row/row0upd.c27
-rw-r--r--innobase/row/row0vers.c18
-rw-r--r--innobase/srv/srv0start.c5
-rw-r--r--innobase/sync/sync0sync.c4
-rw-r--r--innobase/trx/trx0rec.c12
-rw-r--r--innobase/trx/trx0roll.c2
-rw-r--r--innobase/trx/trx0trx.c10
-rw-r--r--innobase/trx/trx0undo.c32
-rw-r--r--innobase/ut/ut0dbg.c65
-rw-r--r--libmysql/libmysql.c27
-rw-r--r--libmysqld/lib_sql.cc2
-rw-r--r--myisam/ft_boolean_search.c2
-rw-r--r--myisam/mi_packrec.c15
-rw-r--r--myisam/myisampack.c1280
-rw-r--r--mysql-test/Makefile.am11
-rw-r--r--mysql-test/README13
-rw-r--r--mysql-test/include/not_openssl.inc4
-rw-r--r--mysql-test/include/ps_create.inc2
-rw-r--r--mysql-test/include/ps_query.inc2
-rw-r--r--mysql-test/include/rpl_stmt_seq.inc201
-rwxr-xr-xmysql-test/include/show_msg.inc10
-rwxr-xr-xmysql-test/include/show_msg80.inc111
-rw-r--r--mysql-test/lib/mtr_cases.pl95
-rw-r--r--mysql-test/lib/mtr_misc.pl52
-rw-r--r--mysql-test/lib/mtr_process.pl2
-rw-r--r--mysql-test/lib/mtr_report.pl7
-rwxr-xr-xmysql-test/mysql-test-run.pl327
-rw-r--r--mysql-test/mysql-test-run.sh8
-rw-r--r--mysql-test/r/alias.result4
-rw-r--r--mysql-test/r/bdb_cache.result4
-rw-r--r--mysql-test/r/case.result15
-rw-r--r--mysql-test/r/cast.result11
-rw-r--r--mysql-test/r/client_xml.result2
-rw-r--r--mysql-test/r/ctype_utf8.result34
-rw-r--r--mysql-test/r/fulltext.result2
-rw-r--r--mysql-test/r/func_date_add.result2
-rw-r--r--mysql-test/r/func_default.result5
-rw-r--r--mysql-test/r/func_encrypt.result56
-rw-r--r--mysql-test/r/func_encrypt_nossl.result93
-rw-r--r--mysql-test/r/func_if.result13
-rw-r--r--mysql-test/r/func_math.result6
-rw-r--r--mysql-test/r/func_str.result13
-rw-r--r--mysql-test/r/func_time.result2
-rw-r--r--mysql-test/r/group_by.result31
-rw-r--r--mysql-test/r/group_min_max.result18
-rw-r--r--mysql-test/r/having.result1
-rw-r--r--mysql-test/r/heap.result8
-rw-r--r--mysql-test/r/heap_hash.result23
-rw-r--r--mysql-test/r/index_merge.result4
-rw-r--r--mysql-test/r/index_merge_innodb.result11
-rw-r--r--mysql-test/r/information_schema.result12
-rw-r--r--mysql-test/r/innodb.result22
-rw-r--r--mysql-test/r/innodb_cache.result2
-rw-r--r--mysql-test/r/insert_select.result24
-rw-r--r--mysql-test/r/insert_update.result2
-rw-r--r--mysql-test/r/join_nested.result22
-rw-r--r--mysql-test/r/join_outer.result8
-rw-r--r--mysql-test/r/lock_multi.result7
-rw-r--r--mysql-test/r/mysql.result6
-rw-r--r--mysql-test/r/mysqldump.result223
-rw-r--r--mysql-test/r/mysqltest.result14
-rw-r--r--mysql-test/r/ndb_autodiscover.result20
-rw-r--r--mysql-test/r/ndb_insert.result16
-rw-r--r--mysql-test/r/not_openssl.require2
-rw-r--r--mysql-test/r/ps.result8
-rw-r--r--mysql-test/r/ps_1general.result2
-rw-r--r--mysql-test/r/ps_2myisam.result4
-rw-r--r--mysql-test/r/ps_3innodb.result4
-rw-r--r--mysql-test/r/ps_4heap.result4
-rw-r--r--mysql-test/r/ps_5merge.result12
-rw-r--r--mysql-test/r/ps_6bdb.result4
-rw-r--r--mysql-test/r/ps_7ndb.result6
-rw-r--r--mysql-test/r/ps_grant.result2
-rw-r--r--mysql-test/r/query_cache.result29
-rw-r--r--mysql-test/r/range.result84
-rw-r--r--mysql-test/r/rpl_ddl.result1077
-rw-r--r--mysql-test/r/rpl_multi_update3.result124
-rw-r--r--mysql-test/r/rpl_sp.result10
-rw-r--r--mysql-test/r/select.result5
-rw-r--r--mysql-test/r/sp-security.result17
-rw-r--r--mysql-test/r/sp.result54
-rw-r--r--mysql-test/r/sp_trans.result4
-rw-r--r--mysql-test/r/sql_mode.result18
-rw-r--r--mysql-test/r/subselect.result23
-rw-r--r--mysql-test/r/trigger.result9
-rw-r--r--mysql-test/r/type_bit.result87
-rw-r--r--mysql-test/r/type_newdecimal.result6
-rw-r--r--mysql-test/r/type_timestamp.result8
-rw-r--r--mysql-test/r/update.result4
-rw-r--r--mysql-test/r/view.result124
-rw-r--r--mysql-test/t/alias.test5
-rw-r--r--mysql-test/t/bdb_cache.test4
-rw-r--r--mysql-test/t/case.test11
-rw-r--r--mysql-test/t/cast.test17
-rw-r--r--mysql-test/t/ctype_utf8.test42
-rw-r--r--mysql-test/t/fulltext.test4
-rw-r--r--mysql-test/t/func_date_add.test2
-rw-r--r--mysql-test/t/func_default.test12
-rw-r--r--mysql-test/t/func_encrypt.test16
-rw-r--r--mysql-test/t/func_encrypt_nossl.test36
-rw-r--r--mysql-test/t/func_if.test12
-rw-r--r--mysql-test/t/func_math.test7
-rw-r--r--mysql-test/t/func_str.test16
-rw-r--r--mysql-test/t/func_time.test2
-rw-r--r--mysql-test/t/group_by.test45
-rw-r--r--mysql-test/t/group_min_max.test13
-rw-r--r--mysql-test/t/heap_hash.test2
-rw-r--r--mysql-test/t/index_merge.test3
-rw-r--r--mysql-test/t/index_merge_innodb.test11
-rw-r--r--mysql-test/t/information_schema.test15
-rw-r--r--mysql-test/t/innodb.test9
-rw-r--r--mysql-test/t/insert_select.test23
-rw-r--r--mysql-test/t/insert_update.test2
-rw-r--r--mysql-test/t/join_nested.test18
-rw-r--r--mysql-test/t/join_outer.test12
-rw-r--r--mysql-test/t/lock_multi.test12
-rw-r--r--mysql-test/t/mysql.test9
-rw-r--r--mysql-test/t/mysqldump.test117
-rw-r--r--mysql-test/t/mysqltest.test20
-rw-r--r--mysql-test/t/ndb_autodiscover.test21
-rw-r--r--mysql-test/t/ndb_insert.test15
-rw-r--r--mysql-test/t/ps.test14
-rw-r--r--mysql-test/t/ps_4heap.test2
-rw-r--r--mysql-test/t/ps_5merge.test4
-rw-r--r--mysql-test/t/query_cache.test32
-rw-r--r--mysql-test/t/range.test58
-rw-r--r--mysql-test/t/rpl_ddl.test350
-rw-r--r--mysql-test/t/rpl_multi_update3.test159
-rw-r--r--mysql-test/t/select.test7
-rw-r--r--mysql-test/t/sp-security.test36
-rw-r--r--mysql-test/t/sp.test29
-rw-r--r--mysql-test/t/sp_trans.test6
-rw-r--r--mysql-test/t/sql_mode.test20
-rw-r--r--mysql-test/t/subselect.test22
-rw-r--r--mysql-test/t/trigger.test14
-rw-r--r--mysql-test/t/type_bit.test53
-rw-r--r--mysql-test/t/type_newdecimal.test9
-rw-r--r--mysql-test/t/update.test4
-rw-r--r--mysql-test/t/view.test127
-rw-r--r--mysys/charset.c2
-rw-r--r--mysys/default.c2
-rw-r--r--mysys/default_modify.c162
-rw-r--r--mysys/mf_iocache.c2
-rw-r--r--mysys/mf_keycache.c2
-rw-r--r--mysys/my_access.c12
-rw-r--r--mysys/my_alloc.c2
-rw-r--r--mysys/my_getopt.c10
-rw-r--r--mysys/my_mmap.c2
-rw-r--r--mysys/my_once.c2
-rw-r--r--mysys/string.c2
-rw-r--r--mysys/tree.c3
-rw-r--r--ndb/include/transporter/TransporterDefinitions.hpp2
-rw-r--r--ndb/src/common/mgmcommon/ConfigRetriever.cpp2
-rw-r--r--ndb/src/common/mgmcommon/IPCConfig.cpp6
-rw-r--r--ndb/src/common/transporter/TransporterRegistry.cpp18
-rw-r--r--ndb/src/common/util/version.c1
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp16
-rw-r--r--ndb/src/kernel/main.cpp6
-rw-r--r--ndb/test/ndbapi/testBlobs.cpp1
-rw-r--r--ndb/test/ndbapi/testTimeout.cpp78
-rw-r--r--netware/my_print_defaults.def3
-rw-r--r--netware/mysql_test_run.c4
-rw-r--r--server-tools/instance-manager/commands.cc61
-rw-r--r--server-tools/instance-manager/protocol.cc39
-rw-r--r--server-tools/instance-manager/protocol.h6
-rw-r--r--sql-common/client.c2
-rw-r--r--sql/Makefile.am13
-rw-r--r--sql/field.cc78
-rw-r--r--sql/field.h14
-rw-r--r--sql/filesort.cc10
-rw-r--r--sql/gstream.cc4
-rw-r--r--sql/ha_federated.cc12
-rw-r--r--sql/ha_heap.cc30
-rw-r--r--sql/ha_heap.h4
-rw-r--r--sql/ha_innodb.cc105
-rw-r--r--sql/ha_innodb.h2
-rw-r--r--sql/ha_myisam.cc2
-rw-r--r--sql/ha_myisammrg.cc2
-rw-r--r--sql/ha_ndbcluster.cc75
-rw-r--r--sql/ha_ndbcluster.h3
-rw-r--r--sql/handler.cc110
-rw-r--r--sql/handler.h8
-rw-r--r--sql/item.cc74
-rw-r--r--sql/item.h77
-rw-r--r--sql/item_buff.cc42
-rw-r--r--sql/item_cmpfunc.cc27
-rw-r--r--sql/item_func.cc55
-rw-r--r--sql/item_func.h39
-rw-r--r--sql/item_strfunc.cc27
-rw-r--r--sql/item_strfunc.h4
-rw-r--r--sql/item_subselect.cc15
-rw-r--r--sql/item_sum.cc22
-rw-r--r--sql/item_sum.h46
-rw-r--r--sql/item_timefunc.cc4
-rw-r--r--sql/item_timefunc.h6
-rw-r--r--sql/item_uniq.h2
-rw-r--r--sql/mysql_priv.h15
-rw-r--r--sql/mysqld.cc61
-rw-r--r--sql/opt_range.cc149
-rw-r--r--sql/password.c8
-rw-r--r--sql/protocol.cc5
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/set_var.h3
-rw-r--r--sql/share/errmsg.txt10
-rw-r--r--sql/slave.cc2
-rw-r--r--sql/sp_head.cc81
-rw-r--r--sql/sp_head.h14
-rw-r--r--sql/sp_rcontext.cc11
-rw-r--r--sql/sp_rcontext.h6
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_base.cc60
-rw-r--r--sql/sql_class.cc136
-rw-r--r--sql/sql_class.h101
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_handler.cc2
-rw-r--r--sql/sql_insert.cc29
-rw-r--r--sql/sql_lex.cc6
-rw-r--r--sql/sql_lex.h27
-rw-r--r--sql/sql_map.cc2
-rw-r--r--sql/sql_parse.cc108
-rw-r--r--sql/sql_prepare.cc155
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_select.cc275
-rw-r--r--sql/sql_select.h44
-rw-r--r--sql/sql_show.cc57
-rw-r--r--sql/sql_table.cc70
-rw-r--r--sql/sql_union.cc55
-rw-r--r--sql/sql_view.cc77
-rw-r--r--sql/sql_yacc.yy76
-rw-r--r--sql/structs.h2
-rw-r--r--sql/table.cc18
-rw-r--r--sql/unireg.cc2
-rw-r--r--strings/ctype-big5.c2
-rw-r--r--strings/ctype-bin.c2
-rw-r--r--strings/ctype-cp932.c2
-rw-r--r--strings/ctype-eucjpms.c10
-rw-r--r--strings/ctype-mb.c6
-rw-r--r--strings/ctype-simple.c10
-rw-r--r--strings/ctype-sjis.c2
-rw-r--r--strings/ctype-uca.c4
-rw-r--r--strings/ctype-ucs2.c18
-rw-r--r--strings/ctype-ujis.c10
-rw-r--r--strings/ctype-utf8.c16
-rw-r--r--strings/ctype.c2
-rw-r--r--strings/decimal.c61
-rw-r--r--strings/xml.c24
-rw-r--r--support-files/mysql.spec.sh15
-rw-r--r--tests/Makefile.am9
-rw-r--r--tests/mysql_client_test.c213
-rw-r--r--tools/Makefile.am7
-rw-r--r--vio/Makefile.am13
-rw-r--r--vio/viosocket.c1
370 files changed, 10202 insertions, 3841 deletions
diff --git a/.bzrignore b/.bzrignore
index ae028ae9426..9c6cf2c965c 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -1116,3 +1116,4 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
+ndb/src/dummy.cpp
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 3d4c3d60ca8..e9cc35b4c7e 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -197,6 +197,7 @@ mysqldev@melody.local
mysqldev@mysql.com
mysqldev@o2k.irixworld.net
ndbdev@dl145b.mysql.com
+ndbdev@dl145c.mysql.com
ndbdev@eel.hemma.oreland.se
ndbdev@ndbmaster.mysql.com
ndbdev@shark.
diff --git a/Docs/Makefile.am b/Docs/Makefile.am
index 6f8c51e79f0..b1f69381774 100644
--- a/Docs/Makefile.am
+++ b/Docs/Makefile.am
@@ -36,22 +36,22 @@ CLEAN_FILES: $(txt_files)
GT = $(srcdir)/Support/generate-text-files.pl
../INSTALL-SOURCE: mysql.info $(GT)
- perl -w $(GT) mysql.info "Installing" "Tutorial" > $@
+ perl -w $(GT) mysql.info "installing-source" "windows-source-build" > $@
../INSTALL-WIN-SOURCE: mysql.info $(GT)
- perl -w $(GT) mysql.info "Windows source build" "Post-installation" > $@
+ perl -w $(GT) mysql.info "windows-source-build" "post-installation" > $@
# We put the description for the binary installation here so that
# people who download source wont have to see it. It is moved up to
# the toplevel by the script that makes the binary tar files.
INSTALL-BINARY: mysql.info $(GT)
- perl -w $(GT) mysql.info "Installing binary" "Installing source" > $@
+ perl -w $(GT) mysql.info "installing-binary" "installing-source" > $@
../EXCEPTIONS-CLIENT: mysql.info $(GT)
- perl -w $(GT) mysql.info "MySQL FLOSS License Exception" "Function Index" > $@
+ perl -w $(GT) mysql.info "mysql-floss-license-exception" "function-index" > $@
../support-files/MacOSX/ReadMe.txt: mysql.info $(GT)
- perl -w $(GT) mysql.info "Mac OS X installation" "NetWare installation" > $@
+ perl -w $(GT) mysql.info "mac-os-x-installation" "netware-installation" > $@
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/Docs/Support/generate-flag-images b/Docs/Support/generate-flag-images
deleted file mode 100755
index 21140388012..00000000000
--- a/Docs/Support/generate-flag-images
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/sh
-
-flags=`grep @image mirrors.texi | cut -d" " -f1 | cut -d/ -f2 | tr -d "}" | sort | uniq`
-
-set -x
-cd Flags
-
-for c in $flags
-do
- # For PNM, to be used later
- giftopnm ../Raw-Flags/$c.gif | pnmscale -xsize 30 > $c-tmp.pnm
- pnmpaste $c-tmp.pnm 1 1 ../Images/flag-background.pnm > $c.pnm
- rm -f $c-tmp.pnm
-
- # For GIF version
- ppmtogif $c.pnm > $c.gif
- # or cjpeg -optimize -quality 70 -outfile $c.jpg
-
- # For EPS version
- pnmtops -noturn $c.pnm > $c.eps
-
- # For PDF version
- ps2pdf $c.eps $c.pdf
-
- # For text version
- echo -n "" > $c.txt
-
- # PNM isn't really needed
- rm -f $c.pnm
-
-done
diff --git a/Docs/Support/generate-text-files.pl b/Docs/Support/generate-text-files.pl
index 6470baaa6e9..0829525f679 100755
--- a/Docs/Support/generate-text-files.pl
+++ b/Docs/Support/generate-text-files.pl
@@ -13,7 +13,7 @@ while (<IN>)
{
if ($in)
{
- if (/Node: $tnode,/)
+ if (/Node: $tnode,/ || /\[index/)
{
$in = 0;
}
diff --git a/Makefile.am b/Makefile.am
index b5ebe8eb8ae..d7059c6adaf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -100,7 +100,8 @@ tags:
# Test installation
test:
- cd mysql-test; ./mysql-test-run && ./mysql-test-run --ps-protocol
+ cd mysql-test; \
+ ./mysql-test-run && ./mysql-test-run --ps-protocol
test-force:
cd mysql-test; \
diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp
index bf6826ddc1f..356aac3563f 100644
--- a/VC++Files/libmysql/libmysql.dsp
+++ b/VC++Files/libmysql/libmysql.dsp
@@ -303,6 +303,10 @@ SOURCE=..\mysys\mulalloc.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\my_access.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\my_alloc.c
# End Source File
# Begin Source File
diff --git a/client/Makefile.am b/client/Makefile.am
index 791da2760a5..a301d55efe4 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -16,6 +16,11 @@
# This file is public domain and comes with NO WARRANTY of any kind
+if HAVE_YASSL
+ yassl_dummy_link_fix= $(top_srcdir)/extra/yassl/src/dummy.cpp
+else
+ yassl_dummy_link_fix=
+endif
#AUTOMAKE_OPTIONS = nostdinc
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/regex \
$(openssl_includes) -I$(top_builddir)/include
@@ -30,12 +35,17 @@ noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
mysql_SOURCES = mysql.cc readline.cc sql_string.cc completion_hash.cc
mysqladmin_SOURCES = mysqladmin.cc
mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS)
-mysqltest_SOURCES= mysqltest.c $(top_srcdir)/mysys/my_getsystime.c
+mysqltest_SOURCES= mysqltest.c $(top_srcdir)/mysys/my_getsystime.c \
+ $(yassl_dummy_link_fix)
mysqltest_LDADD = $(top_builddir)/regex/libregex.a $(LDADD)
mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c $(top_srcdir)/mysys/my_new.cc
mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS)
-mysqltestmanagerc_SOURCES = mysqlmanagerc.c
mysqltestmanager_pwgen_SOURCES = mysqlmanager-pwgen.c
+mysqltestmanagerc_SOURCES= mysqlmanagerc.c $(yassl_dummy_link_fix)
+mysqlcheck_SOURCES= mysqlcheck.c $(yassl_dummy_link_fix)
+mysqlshow_SOURCES= mysqlshow.c $(yassl_dummy_link_fix)
+mysqldump_SOURCES= mysqldump.c $(yassl_dummy_link_fix)
+mysqlimport_SOURCES= mysqlimport.c $(yassl_dummy_link_fix)
sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc
strings_src=decimal.c
diff --git a/client/mysql.cc b/client/mysql.cc
index 96b523d8dc8..f98bf467588 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1011,7 +1011,8 @@ static int read_lines(bool execute_commands)
a nil, it still needs the space in the linebuffer for it. This is,
naturally, undocumented.
*/
- } while (linebuffer[0] <= linebuffer[1] + 1);
+ } while ((unsigned char)linebuffer[0] <=
+ (unsigned char)linebuffer[1] + 1);
line= buffer.c_ptr();
#endif /* __NETWARE__ */
#else
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 907b6233590..c75f02353b4 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -57,6 +57,7 @@
#define EX_CONSCHECK 3
#define EX_EOM 4
#define EX_EOF 5 /* ferror for output file was got */
+#define EX_ILLEGAL_TABLE 6
/* index into 'show fields from table' */
@@ -142,14 +143,6 @@ const char *compatible_mode_names[]=
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
"", compatible_mode_names, NULL};
-#define TABLE_RULE_HASH_SIZE 16
-
-typedef struct st_table_rule_ent
-{
- char* key; /* dbname.tablename */
- uint key_len;
-} TABLE_RULE_ENT;
-
HASH ignore_table;
static struct my_option my_long_options[] =
@@ -476,7 +469,10 @@ static void write_header(FILE *sql_file, char *db_name)
if (opt_xml)
{
fputs("<?xml version=\"1.0\"?>\n", sql_file);
- fputs("<mysqldump>\n", sql_file);
+ fputs("<mysqldump ", sql_file);
+ fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
+ sql_file);
+ fputs(">\n", sql_file);
check_io(sql_file);
}
else if (!opt_compact)
@@ -544,29 +540,21 @@ static void write_footer(FILE *sql_file)
} /* write_footer */
-static void free_table_ent(TABLE_RULE_ENT* e)
-{
- my_free((gptr) e, MYF(0));
-}
-
-
-static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
- my_bool not_used __attribute__((unused)))
+byte* get_table_key(const char *entry, uint *length,
+ my_bool not_used __attribute__((unused)))
{
- *len= e->key_len;
- return (byte*)e->key;
+ *length= strlen(entry);
+ return (byte*) entry;
}
void init_table_rule_hash(HASH* h)
{
- if(hash_init(h, charset_info, TABLE_RULE_HASH_SIZE, 0, 0,
- (hash_get_key) get_table_key,
- (hash_free_key) free_table_ent, 0))
+ if(hash_init(h, charset_info, 16, 0, 0,
+ (hash_get_key) get_table_key, 0, 0))
exit(EX_EOM);
}
-
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
@@ -639,25 +627,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case (int) OPT_IGNORE_TABLE:
{
- uint len= (uint)strlen(argument);
- TABLE_RULE_ENT* e;
if (!strchr(argument, '.'))
{
fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n");
exit(1);
}
- /* len is always > 0 because we know the there exists a '.' */
- e= (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT) + len, MYF(MY_WME));
- if (!e)
- exit(EX_EOM);
- e->key= (char*)e + sizeof(TABLE_RULE_ENT);
- e->key_len= len;
- memcpy(e->key, argument, len);
-
if (!hash_inited(&ignore_table))
init_table_rule_hash(&ignore_table);
- if(my_hash_insert(&ignore_table, (byte*)e))
+ if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0))))
exit(EX_EOM);
break;
}
@@ -980,7 +958,28 @@ static char *quote_name(const char *name, char *buff, my_bool force)
return buff;
} /* quote_name */
+/*
+ Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
+ SYNOPSIS
+ quote_for_like
+ name - name of the table
+ buff - quoted name of the table
+
+ DESCRIPTION
+ Quote \, _, ' and % characters
+
+ Note: Because MySQL uses the C escape syntax in strings
+ (for example, '\n' to represent newline), you must double
+ any '\' that you use in your LIKE strings. For example, to
+ search for '\n', specify it as '\\n'. To search for '\', specify
+ it as '\\\\' (the backslashes are stripped once by the parser
+ and another time when the pattern match is done, leaving a
+ single backslash to be matched).
+
+ Example: "t\1" => "t\\\\1"
+
+*/
static char *quote_for_like(const char *name, char *buff)
{
@@ -988,7 +987,13 @@ static char *quote_for_like(const char *name, char *buff)
*to++= '\'';
while (*name)
{
- if (*name == '\'' || *name == '_' || *name == '\\' || *name == '%')
+ if (*name == '\\')
+ {
+ *to++='\\';
+ *to++='\\';
+ *to++='\\';
+ }
+ else if (*name == '\'' || *name == '_' || *name == '%')
*to++= '\\';
*to++= *name++;
}
@@ -1074,6 +1079,40 @@ static void print_xml_tag1(FILE * xml_file, const char* sbeg,
/*
+ Print xml tag with for a field that is null
+
+ SYNOPSIS
+ print_xml_null_tag()
+ xml_file - output file
+ sbeg - line beginning
+ stag_atr - tag and attribute
+ sval - value of attribute
+ send - line ending
+
+ DESCRIPTION
+ Print tag with one attribute to the xml_file. Format is:
+ <stag_atr="sval" xsi:nil="true"/>
+ NOTE
+ sval MUST be a NULL terminated string.
+ sval string will be qouted before output.
+*/
+
+static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
+ const char* stag_atr, const char* sval,
+ const char* send)
+{
+ fputs(sbeg, xml_file);
+ fputs("<", xml_file);
+ fputs(stag_atr, xml_file);
+ fputs("\"", xml_file);
+ print_quoted_xml(xml_file, sval, strlen(sval));
+ fputs("\" xsi:nil=\"true\" />", xml_file);
+ fputs(send, xml_file);
+ check_io(xml_file);
+}
+
+
+/*
Print xml tag with many attributes.
SYNOPSIS
@@ -1139,6 +1178,7 @@ static uint get_table_structure(char *table, char *db)
FILE *sql_file = md_result_file;
int len;
DBUG_ENTER("get_table_structure");
+ DBUG_PRINT("enter", ("db: %s, table: %s", db, table));
if (!insert_pat_inited)
{
@@ -1592,6 +1632,26 @@ static void dump_table(uint numFields, char *table)
const char *table_type;
int error= 0;
+ /* Check --no-data flag */
+ if (dFlag)
+ {
+ if (verbose)
+ fprintf(stderr,
+ "-- Skipping dump data for table '%s', --no-data was used\n",
+ table);
+ return;
+ }
+
+ /* Check that there are any fields in the table */
+ if(numFields == 0)
+ {
+ if (verbose)
+ fprintf(stderr,
+ "-- Skipping dump data for table '%s', it has no fields\n",
+ table);
+ return;
+ }
+
result_table= quote_name(table,table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
@@ -1912,7 +1972,14 @@ static void dump_table(uint numFields, char *table)
}
}
else
- fputs("NULL", md_result_file);
+ {
+ /* The field value is NULL */
+ if (!opt_xml)
+ fputs("NULL", md_result_file);
+ else
+ print_xml_null_tag(md_result_file, "\t\t", "field name=",
+ field->name, "\n");
+ }
check_io(md_result_file);
}
}
@@ -2201,8 +2268,7 @@ static int dump_all_tables_in_db(char *database)
if (include_table(hash_key, end - hash_key))
{
numrows = get_table_structure(table, database);
- if (!dFlag && numrows > 0)
- dump_table(numrows,table);
+ dump_table(numrows,table);
my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
order_by= 0;
}
@@ -2327,27 +2393,61 @@ static int get_actual_table_name(const char *old_table_name,
static int dump_selected_tables(char *db, char **table_names, int tables)
{
- uint numrows;
- int i;
+ uint numrows, i;
char table_buff[NAME_LEN*+3];
+ char new_table_name[NAME_LEN];
+ DYNAMIC_STRING lock_tables_query;
+ HASH dump_tables;
+ char *table_name;
+
+ DBUG_ENTER("dump_selected_tables");
if (init_dumping(db))
return 1;
- if (lock_tables)
+
+ /* Init hash table for storing the actual name of tables to dump */
+ if (hash_init(&dump_tables, charset_info, 16, 0, 0,
+ (hash_get_key) get_table_key, 0, 0))
+ exit(EX_EOM);
+
+ init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024);
+ for (; tables > 0 ; tables-- , table_names++)
{
- DYNAMIC_STRING query;
+ /* the table name passed on commandline may be wrong case */
+ if (!get_actual_table_name( *table_names,
+ new_table_name, sizeof(new_table_name) ))
+ {
+ /* Add found table name to lock_tables_query */
+ if (lock_tables)
+ {
+ dynstr_append(&lock_tables_query,
+ quote_name(new_table_name, table_buff, 1));
+ dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,");
+ }
- init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
- for (i=0 ; i < tables ; i++)
+ /* Add found table name to dump_tables list */
+ if (my_hash_insert(&dump_tables,
+ (byte*)my_strdup(new_table_name, MYF(0))))
+ exit(EX_EOM);
+
+ }
+ else
{
- dynstr_append(&query, quote_name(table_names[i], table_buff, 1));
- dynstr_append(&query, " READ /*!32311 LOCAL */,");
+ my_printf_error(0,"Couldn't find table: \"%s\"\n", MYF(0),
+ *table_names);
+ safe_exit(EX_ILLEGAL_TABLE);
+ /* We shall countinue here, if --force was given */
}
- if (mysql_real_query(sock, query.str, query.length-1))
+ }
+
+ if (lock_tables)
+ {
+ if (mysql_real_query(sock, lock_tables_query.str,
+ lock_tables_query.length-1))
DB_error(sock, "when doing LOCK TABLES");
/* We shall countinue here, if --force was given */
- dynstr_free(&query);
}
+ dynstr_free(&lock_tables_query);
if (flush_logs)
{
if (mysql_refresh(sock, REFRESH_LOG))
@@ -2356,25 +2456,28 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
}
if (opt_xml)
print_xml_tag1(md_result_file, "", "database name=", db, "\n");
- for (i=0 ; i < tables ; i++)
- {
- char new_table_name[NAME_LEN];
- /* the table name passed on commandline may be wrong case */
- if (!get_actual_table_name( table_names[i], new_table_name,
- sizeof(new_table_name)))
- {
- numrows= get_table_structure(new_table_name, db);
- dump_table(numrows, new_table_name);
- }
- my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
- order_by= 0;
+ /* Dump each selected table */
+ for (i= 0; i < dump_tables.records; i++)
+ {
+ table_name= hash_element(&dump_tables, i);
+ DBUG_PRINT("info",("Dumping table %s", table_name));
+ numrows = get_table_structure(table_name, db);
+ dump_table(numrows, table_name);
}
+
+ /* Dump each selected view */
if (was_views)
{
- for (i=0 ; i < tables ; i++)
- get_view_structure(table_names[i], db);
+ for(i=0; i < dump_tables.records; i++)
+ {
+ table_name= hash_element(&dump_tables, i);
+ get_view_structure(table_name, db);
+ }
}
+ hash_free(&dump_tables);
+ my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
+ order_by= 0;
if (opt_xml)
{
fputs("</database>\n", md_result_file);
@@ -2382,7 +2485,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
}
if (lock_tables)
mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
- return 0;
+ DBUG_RETURN(0);
} /* dump_selected_tables */
@@ -2776,7 +2879,7 @@ int main(int argc, char **argv)
compatible_mode_normal_str[0]= 0;
default_charset= (char *)mysql_universal_client_charset;
- MY_INIT(argv[0]);
+ MY_INIT("mysqldump");
if (get_options(&argc, &argv))
{
my_end(0);
diff --git a/client/mysqltest.c b/client/mysqltest.c
index c172d18cbd0..a7f9420df6d 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -60,6 +60,7 @@
#include <sys/stat.h>
#include <violite.h>
#include <regex.h> /* Our own version of lib */
+#include <sys/wait.h>
#define MAX_QUERY 131072
#define MAX_VAR_NAME 256
#define MAX_COLUMNS 256
@@ -164,10 +165,17 @@ static char TMPDIR[FN_REFLEN];
static char delimiter[MAX_DELIMITER]= DEFAULT_DELIMITER;
static uint delimiter_length= 1;
-static int *cur_block, *block_stack_end;
-static int block_stack[BLOCK_STACK_DEPTH];
+/* Block stack */
+enum block_cmd { cmd_none, cmd_if, cmd_while };
+typedef struct
+{
+ int line; /* Start line of block */
+ my_bool ok; /* Should block be executed */
+ enum block_cmd cmd; /* Command owning the block */
+} BLOCK;
+static BLOCK block_stack[BLOCK_STACK_DEPTH];
+static BLOCK *cur_block, *block_stack_end;
-static int block_ok_stack[BLOCK_STACK_DEPTH];
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
static const char *charset_name= "latin1"; /* Default character set name */
@@ -221,8 +229,6 @@ MYSQL_RES *last_result=0;
PARSER parser;
MASTER_POS master_pos;
-int *block_ok; /* set to 0 if the current block should not be executed */
-int false_block_depth = 0;
/* if set, all results are concated and compared against this file */
const char *result_file = 0;
@@ -296,6 +302,7 @@ Q_START_TIMER, Q_END_TIMER,
Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
Q_EXIT,
Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
+Q_IF,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
@@ -386,6 +393,7 @@ const char *command_names[]=
"exit",
"disable_reconnect",
"enable_reconnect",
+ "if",
0
};
@@ -979,9 +987,38 @@ static void do_exec(struct st_query* q)
replace_dynstr_append(ds, buf);
}
error= pclose(res_file);
-
if (error != 0)
- die("command \"%s\" failed", cmd);
+ {
+ uint status= WEXITSTATUS(error);
+ if(q->abort_on_error)
+ die("At line %u: command \"%s\" failed", start_lineno, cmd);
+ else
+ {
+ bool ok= 0;
+ uint i;
+ DBUG_PRINT("info",
+ ("error: %d, status: %d", error, status));
+ for (i=0 ; (uint) i < q->expected_errors ; i++)
+ {
+ DBUG_PRINT("info", ("expected error: %d", q->expected_errno[i].code.errnum));
+ if ((q->expected_errno[i].type == ERR_ERRNO) &&
+ (q->expected_errno[i].code.errnum == status))
+ ok= 1;
+ verbose_msg("At line %u: command \"%s\" failed with expected error: %d",
+ start_lineno, cmd, status);
+ }
+ if (!ok)
+ die("At line: %u: command \"%s\" failed with wrong error: %d",
+ start_lineno, cmd, status);
+ }
+ }
+ else if (q->expected_errno[0].type == ERR_ERRNO &&
+ q->expected_errno[0].code.errnum != 0)
+ {
+ /* Error code we wanted was != 0, i.e. not an expected success */
+ die("At line: %u: command \"%s\" succeeded - should have failed with errno %d...",
+ start_lineno, cmd, q->expected_errno[0].code.errnum);
+ }
if (!disable_result_log)
{
@@ -1924,36 +1961,54 @@ int do_connect(struct st_query* q)
int do_done(struct st_query* q)
{
+ /* Dummy statement to eliminate compiler warning */
q->type = Q_END_BLOCK;
+
+ /* Check if empty block stack */
if (cur_block == block_stack)
die("Stray '}' - end of block before beginning");
- if (*block_ok--)
+
+ /* Test if inner block has been executed */
+ if (cur_block->ok && cur_block->cmd == cmd_while)
{
- parser.current_line = *--cur_block;
+ /* Pop block from stack, re-execute outer block */
+ cur_block--;
+ parser.current_line = cur_block->line;
}
else
{
- ++parser.current_line;
- --cur_block;
+ /* Pop block from stack, goto next line */
+ cur_block--;
+ parser.current_line++;
}
return 0;
}
-int do_while(struct st_query* q)
+
+int do_block(enum block_cmd cmd, struct st_query* q)
{
char* p=q->first_argument;
const char* expr_start, *expr_end;
VAR v;
+
+ /* Check stack overflow */
if (cur_block == block_stack_end)
die("Nesting too deeply");
- if (!*block_ok)
+
+ /* Set way to find outer block again, increase line counter */
+ cur_block->line= parser.current_line++;
+
+ /* If this block is ignored */
+ if (!cur_block->ok)
{
- ++false_block_depth;
- *++block_ok = 0;
- *cur_block++ = parser.current_line++;
+ /* Inner block should be ignored too */
+ cur_block++;
+ cur_block->cmd= cmd;
+ cur_block->ok= FALSE;
return 0;
}
+ /* Parse and evaluate test expression */
expr_start = strchr(p, '(');
if (!expr_start)
die("missing '(' in while");
@@ -1962,14 +2017,12 @@ int do_while(struct st_query* q)
die("missing ')' in while");
var_init(&v,0,0,0,0);
eval_expr(&v, ++expr_start, &expr_end);
- *cur_block++ = parser.current_line++;
- if (!v.int_val)
- {
- *++block_ok = 0;
- false_block_depth++;
- }
- else
- *++block_ok = 1;
+
+ /* Define inner block */
+ cur_block++;
+ cur_block->cmd= cmd;
+ cur_block->ok= (v.int_val ? TRUE : FALSE);
+
var_free(&v);
return 0;
}
@@ -3653,12 +3706,13 @@ int main(int argc, char **argv)
lineno = lineno_stack;
my_init_dynamic_array(&q_lines, sizeof(struct st_query*), INIT_Q_LINES,
INIT_Q_LINES);
+
memset(block_stack, 0, sizeof(block_stack));
- block_stack_end = block_stack + BLOCK_STACK_DEPTH;
- memset(block_ok_stack, 0, sizeof(block_stack));
- cur_block = block_stack;
- block_ok = block_ok_stack;
- *block_ok = 1;
+ block_stack_end= block_stack + BLOCK_STACK_DEPTH;
+ cur_block= block_stack;
+ cur_block->ok= TRUE; /* Outer block should always be executed */
+ cur_block->cmd= cmd_none;
+
init_dynamic_string(&ds_res, "", 0, 65536);
parse_args(argc, argv);
@@ -3712,7 +3766,7 @@ int main(int argc, char **argv)
int current_line_inc = 1, processed = 0;
if (q->type == Q_UNKNOWN || q->type == Q_COMMENT_WITH_COMMAND)
get_query_type(q);
- if (*block_ok)
+ if (cur_block->ok)
{
processed = 1;
switch (q->type) {
@@ -3915,7 +3969,8 @@ int main(int argc, char **argv)
{
current_line_inc = 0;
switch (q->type) {
- case Q_WHILE: do_while(q); break;
+ case Q_WHILE: do_block(cmd_while, q); break;
+ case Q_IF: do_block(cmd_if, q); break;
case Q_END_BLOCK: do_done(q); break;
default: current_line_inc = 1; break;
}
diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4
index e2564c2b80a..6f93f38f119 100644
--- a/config/ac-macros/misc.m4
+++ b/config/ac-macros/misc.m4
@@ -710,3 +710,59 @@ fi
])
+AC_DEFUN([MYSQL_CHECK_CXX_VERSION], [
+case $SYSTEM_TYPE in
+ *netware*)
+ CXX_VERSION=`$CXX -version | grep -i version`
+ ;;
+ *)
+ CXX_VERSION=`$CXX --version | sed 1q`
+ if test $? -ne "0" -o -z "$CXX_VERSION"
+ then
+ CXX_VERSION=`$CXX -V 2>&1|sed 1q` # trying harder for Sun and SGI
+ fi
+ if test $? -ne "0" -o -z "$CXX_VERSION"
+ then
+ CXX_VERSION=`$CXX -v 2>&1|sed 1q` # even harder for Alpha
+ fi
+ if test $? -ne "0" -o -z "$CXX_VERSION"
+ then
+ CXX_VERSION=""
+ fi
+esac
+if test "$CXX_VERSION"
+then
+ AC_MSG_CHECKING("C++ compiler version");
+ AC_MSG_RESULT("$CXX $CXX_VERSION")
+fi
+AC_SUBST(CXX_VERSION)
+])
+
+AC_DEFUN([MYSQL_PROG_AR], [
+AC_REQUIRE([MYSQL_CHECK_CXX_VERSION])
+case $CXX_VERSION in
+ MIPSpro*)
+ AR=$CXX
+ ARFLAGS="-ar -o"
+ ;;
+ *Forte*)
+ AR=$CXX
+ ARFLAGS="-xar -o"
+ ;;
+ *)
+ if test -z "$AR"
+ then
+ AC_CHECK_PROG([AR], [ar], [ar])
+ fi
+ if test -z "$AR"
+ then
+ AC_MSG_ERROR([You need ar to build the library])
+ fi
+ if test -z "$ARFLAGS"
+ then
+ ARFLAGS="cru"
+ fi
+esac
+AC_SUBST(AR)
+AC_SUBST(ARFLAGS)
+])
diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4
index ddacde51c2a..fb7c89181df 100644
--- a/config/ac-macros/yassl.m4
+++ b/config/ac-macros/yassl.m4
@@ -30,4 +30,5 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [
AC_SUBST(openssl_libs)
AC_SUBST(openssl_includes)
AC_SUBST(yassl_dir)
+ AM_CONDITIONAL([HAVE_YASSL], [ test "$yassl" = "yes" ])
])
diff --git a/configure.in b/configure.in
index 08b739c5782..a37963911b9 100644
--- a/configure.in
+++ b/configure.in
@@ -1,12 +1,12 @@
dnl -*- ksh -*-
dnl Process this file with autoconf to produce a configure script.
-AC_PREREQ(2.50)dnl Minimum Autoconf version required.
+AC_PREREQ(2.58)dnl Minimum Autoconf version required.
AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM
# Don't forget to also update the NDB lines below.
-AM_INIT_AUTOMAKE(mysql, 5.0.8-beta)
+AM_INIT_AUTOMAKE(mysql, 5.0.9-beta)
AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
@@ -17,7 +17,7 @@ SHARED_LIB_VERSION=14:0:0
# ndb version
NDB_VERSION_MAJOR=5
NDB_VERSION_MINOR=0
-NDB_VERSION_BUILD=8
+NDB_VERSION_BUILD=9
NDB_VERSION_STATUS="beta"
# Set all version vars based on $VERSION. How do we do this more elegant ?
@@ -195,23 +195,8 @@ then
else
CC_VERSION=""
fi
-case $SYSTEM_TYPE in
- *netware*)
-CXX_VERSION=`$CXX -version | grep -i version`
- ;;
- *)
-CXX_VERSION=`$CXX --version | sed 1q`
- ;;
-esac
-if test $? -eq "0"
-then
- AC_MSG_CHECKING("C++ compiler version");
- AC_MSG_RESULT("$CXX $CXX_VERSION")
-else
-CXX_VERSION=""
-fi
-AC_SUBST(CXX_VERSION)
AC_SUBST(CC_VERSION)
+MYSQL_CHECK_CXX_VERSION
# Fix for sgi gcc / sgiCC which tries to emulate gcc
if test "$CC" = "sgicc"
@@ -357,7 +342,7 @@ AC_SUBST(CXXFLAGS)
AC_SUBST(LD)
AC_SUBST(INSTALL_SCRIPT)
-export CC CXX CFLAGS LD LDFLAGS AR
+export CC CXX CFLAGS LD LDFLAGS AR ARFLAGS
if test "$GCC" = "yes"
then
@@ -365,8 +350,12 @@ then
# Disable exceptions as they seams to create problems with gcc and threads.
# mysqld doesn't use run-time-type-checking, so we disable it.
CXXFLAGS="$CXXFLAGS -fno-implicit-templates -fno-exceptions -fno-rtti"
+ AC_DEFINE([HAVE_EXPLICIT_TEMPLATE_INSTANTIATION],
+ [1], [Defined by configure. Use explicit template instantiation.])
fi
+MYSQL_PROG_AR
+
# Avoid bug in fcntl on some versions of linux
AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os")
# Any variation of Linux
@@ -2273,7 +2262,7 @@ AC_ARG_WITH([mysqlmanager],
[if test "x${withval}" != "xno"; then
tools_dirs="$tools_dirs server-tools"
fi],
- [if test "x${with_server}" == "xyes"; then
+ [if test "x${with_server}" = "xyes"; then
tools_dirs="$tools_dirs server-tools"
fi]
)
diff --git a/extra/yassl/include/lock.hpp b/extra/yassl/include/lock.hpp
index 11a623879d4..f5231528821 100644
--- a/extra/yassl/include/lock.hpp
+++ b/extra/yassl/include/lock.hpp
@@ -31,7 +31,7 @@ namespace yaSSL {
#ifdef MULTI_THREADED
- #ifdef WIN32
+ #ifdef _WIN32
#include <windows.h>
class Mutex {
@@ -50,7 +50,7 @@ namespace yaSSL {
~Lock();
};
};
- #else // WIN32
+ #else // _WIN32
#include <pthread.h>
class Mutex {
@@ -71,7 +71,7 @@ namespace yaSSL {
};
};
- #endif // WIN32
+ #endif // _WIN32
#else // MULTI_THREADED (WE'RE SINGLE)
class Mutex {
diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp
index a103cca1b37..38a9ce3bd25 100644
--- a/extra/yassl/include/socket_wrapper.hpp
+++ b/extra/yassl/include/socket_wrapper.hpp
@@ -31,7 +31,7 @@
#include <assert.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/time.h>
@@ -47,7 +47,7 @@ namespace yaSSL {
typedef unsigned int uint;
-#ifdef WIN32
+#ifdef _WIN32
typedef SOCKET socket_t;
#else
typedef int socket_t;
diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp
index d3f7754f074..60a78a3970e 100644
--- a/extra/yassl/include/yassl_int.hpp
+++ b/extra/yassl/include/yassl_int.hpp
@@ -164,7 +164,12 @@ private:
// openSSL bignum
struct BIGNUM {
- Integer int_;
+ /*
+ gcc 2.96 fix: because of two Integer classes (yaSSL::Integer and
+ TaoCrypt::Integer), we need to explicitly state the namespace
+ here to let gcc 2.96 deduce the correct type.
+ */
+ yaSSL::Integer int_;
void assign(const byte* b, uint s) { int_.assign(b,s); }
};
diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp
index d1d3fb829de..01b82d95039 100644
--- a/extra/yassl/include/yassl_types.hpp
+++ b/extra/yassl/include/yassl_types.hpp
@@ -445,6 +445,15 @@ const opaque master_label[MASTER_LABEL_SZ + 1] = "master secret";
const opaque key_label [KEY_LABEL_SZ + 1] = "key expansion";
-} // naemspace
+} // namespace
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
+/*
+ gcc 2.96 bails out because of two declarations of byte: yaSSL::byte and
+ TaoCrypt::byte. TODO: define global types.hpp and move the declaration of
+ 'byte' there.
+*/
+using yaSSL::byte;
+#endif
#endif // yaSSL_TYPES_HPP
diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/mySTL/helpers.hpp
index 5f9b4beaa40..8d2061fc4f1 100644
--- a/extra/yassl/mySTL/helpers.hpp
+++ b/extra/yassl/mySTL/helpers.hpp
@@ -31,32 +31,39 @@
#include <new> // placement new
+
#ifdef __IBMCPP__
/*
- Workaround for the lack of operator new(size_t, void*)
- in IBM VA C++ 6.0
+ Workaround for the lack of operator new(size_t, void*)
+ in IBM VA C++ 6.0
*/
-struct Dummy {};
-inline void *operator new(size_t size, Dummy *d) { return (void*) d; }
-typedef Dummy *yassl_pointer;
+ struct Dummy {};
+
+ inline void* operator new(size_t size, Dummy* d)
+ {
+ return static_cast<void*>(d);
+ }
+
+ typedef Dummy* yassl_pointer;
#else
-typedef void *yassl_pointer;
+ typedef void* yassl_pointer;
#endif
+
namespace mySTL {
template <typename T, typename T2>
inline void construct(T* p, const T2& value)
{
- new ((yassl_pointer) p) T(value);
+ new (reinterpret_cast<yassl_pointer>(p)) T(value);
}
template <typename T>
inline void construct(T* p)
{
- new (static_cast<void*>(p)) T();
+ new (reinterpret_cast<yassl_pointer>(p)) T();
}
diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp
index ff1b4b630c2..80cadd3d722 100644
--- a/extra/yassl/src/crypto_wrapper.cpp
+++ b/extra/yassl/src/crypto_wrapper.cpp
@@ -971,7 +971,7 @@ x509* PemToDer(const char* fname, CertType type)
} // namespace
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
namespace yaSSL {
template void ysDelete<DiffieHellman::DHImpl>(DiffieHellman::DHImpl*);
template void ysDelete<Integer::IntegerImpl>(Integer::IntegerImpl*);
@@ -989,6 +989,6 @@ template void ysDelete<RMD::RMDImpl>(RMD::RMDImpl*);
template void ysDelete<SHA::SHAImpl>(SHA::SHAImpl*);
template void ysDelete<MD5::MD5Impl>(MD5::MD5Impl*);
}
-#endif // __GNUC__
+#endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
#endif // !USE_CRYPTOPP_LIB
diff --git a/extra/yassl/src/lock.cpp b/extra/yassl/src/lock.cpp
index b8f6212ad3f..8a0b66ead42 100644
--- a/extra/yassl/src/lock.cpp
+++ b/extra/yassl/src/lock.cpp
@@ -29,7 +29,7 @@ namespace yaSSL {
#ifdef MULTI_THREADED
- #ifdef WIN32
+ #ifdef _WIN32
Mutex::Mutex()
{
@@ -54,7 +54,7 @@ namespace yaSSL {
LeaveCriticalSection(&mutex_.cs_);
}
- #else // WIN32
+ #else // _WIN32
Mutex::Mutex()
{
@@ -80,7 +80,7 @@ namespace yaSSL {
}
- #endif // WIN32
+ #endif // _WIN32
#endif // MULTI_THREADED
diff --git a/extra/yassl/src/log.cpp b/extra/yassl/src/log.cpp
index 538b80b8280..38633cd1210 100644
--- a/extra/yassl/src/log.cpp
+++ b/extra/yassl/src/log.cpp
@@ -78,8 +78,8 @@ namespace yaSSL {
}
- #if defined(WIN32) || defined(__MACH__) || defined(__hpux__)
- typedef int socklen_t;
+ #if defined(_WIN32) || defined(__MACH__) || defined(__hpux__)
+ typedef int socklen_t;
#endif
diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp
index 1be6a715980..00f9c8d170c 100644
--- a/extra/yassl/src/socket_wrapper.cpp
+++ b/extra/yassl/src/socket_wrapper.cpp
@@ -28,7 +28,7 @@
#include "socket_wrapper.hpp"
-#ifndef WIN32
+#ifndef _WIN32
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
@@ -36,19 +36,19 @@
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <string.h>
-#endif // WIN32
+#endif // _WIN32
#ifdef __sun
#include <sys/filio.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
const int SOCKET_EINVAL = WSAEINVAL;
const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
#else
const int SOCKET_EINVAL = EINVAL;
const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
-#endif // WIN32
+#endif // _WIN32
namespace yaSSL {
@@ -80,7 +80,7 @@ Socket::~Socket()
void Socket::closeSocket()
{
if (socket_ != INVALID_SOCKET) {
-#ifdef WIN32
+#ifdef _WIN32
closesocket(socket_);
#else
close(socket_);
@@ -94,7 +94,7 @@ uint Socket::get_ready() const
{
unsigned long ready = 0;
-#ifdef WIN32
+#ifdef _WIN32
ioctlsocket(socket_, FIONREAD, &ready);
#else
ioctl(socket_, FIONREAD, &ready);
@@ -145,7 +145,7 @@ void Socket::shutDown(int how)
int Socket::get_lastError()
{
-#ifdef WIN32
+#ifdef _WIN32
return WSAGetLastError();
#else
return errno;
@@ -155,7 +155,7 @@ int Socket::get_lastError()
void Socket::set_lastError(int errorCode)
{
-#ifdef WIN32
+#ifdef _WIN32
WSASetLastError(errorCode);
#else
errno = errorCode;
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
index a82afcd4aad..d37c44049b2 100644
--- a/extra/yassl/src/ssl.cpp
+++ b/extra/yassl/src/ssl.cpp
@@ -32,11 +32,11 @@
/* see man pages for function descriptions */
+#include "runtime.hpp"
#include "openssl/ssl.h"
#include "handshake.hpp"
#include "yassl_int.hpp"
#include <stdio.h>
-#include "runtime.hpp"
namespace yaSSL {
diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp
index 4ad1ec29249..5cf4f8c39f8 100644
--- a/extra/yassl/src/template_instnt.cpp
+++ b/extra/yassl/src/template_instnt.cpp
@@ -8,7 +8,7 @@
#include "ripemd.hpp"
#include "openssl/ssl.h"
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
#if !defined(USE_CRYPTOPP_LIB)
namespace TaoCrypt {
template class HMAC<MD5>;
@@ -18,26 +18,26 @@ template class HMAC<RIPEMD160>;
#endif
namespace mySTL {
-template class mySTL::list<unsigned char*>;
-template yaSSL::del_ptr_zero mySTL::for_each(mySTL::list<unsigned char*>::iterator, mySTL::list<unsigned char*>::iterator, yaSSL::del_ptr_zero);
-template mySTL::pair<int, yaSSL::Message* (*)()>* mySTL::uninit_copy<mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
-template mySTL::pair<int, yaSSL::HandShakeBase* (*)()>* mySTL::uninit_copy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
-template void mySTL::destroy<mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
-template void mySTL::destroy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
-template mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>* mySTL::uninit_copy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
-template void mySTL::destroy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
-template mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>* mySTL::uninit_copy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
-template class mySTL::list<TaoCrypt::Signer*>;
-template class mySTL::list<yaSSL::SSL_SESSION*>;
-template class mySTL::list<yaSSL::input_buffer*>;
-template class mySTL::list<yaSSL::output_buffer*>;
-template class mySTL::list<yaSSL::x509*>;
-template void mySTL::destroy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
-template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<TaoCrypt::Signer*>::iterator, mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero);
-template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::x509*>::iterator, mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero);
+template class list<unsigned char*>;
+template yaSSL::del_ptr_zero for_each(mySTL::list<unsigned char*>::iterator, mySTL::list<unsigned char*>::iterator, yaSSL::del_ptr_zero);
+template pair<int, yaSSL::Message* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
+template pair<int, yaSSL::HandShakeBase* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
+template void destroy<mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
+template void destroy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
+template pair<int, yaSSL::ServerKeyBase* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
+template void destroy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
+template pair<int, yaSSL::ClientKeyBase* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
+template class list<TaoCrypt::Signer*>;
+template class list<yaSSL::SSL_SESSION*>;
+template class list<yaSSL::input_buffer*>;
+template class list<yaSSL::output_buffer*>;
+template class list<yaSSL::x509*>;
+template void destroy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
+template yaSSL::del_ptr_zero for_each<mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<TaoCrypt::Signer*>::iterator, mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::x509*>::iterator, mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero);
}
namespace yaSSL {
diff --git a/extra/yassl/src/timer.cpp b/extra/yassl/src/timer.cpp
index 547c31205c6..cfa1319ae80 100644
--- a/extra/yassl/src/timer.cpp
+++ b/extra/yassl/src/timer.cpp
@@ -27,7 +27,7 @@
namespace yaSSL {
-#ifdef WIN32
+#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -54,7 +54,7 @@ namespace yaSSL {
return static_cast<uint>(timer());
}
-#else // WIN32
+#else // _WIN32
#include <sys/time.h>
@@ -77,5 +77,5 @@ namespace yaSSL {
}
-#endif // WIN32
+#endif // _WIN32
} // namespace yaSSL
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
index 06be7a15503..e9c1ed53816 100644
--- a/extra/yassl/src/yassl_int.cpp
+++ b/extra/yassl/src/yassl_int.cpp
@@ -24,6 +24,7 @@
* draft along with type conversion functions.
*/
+#include "runtime.hpp"
#include "yassl_int.hpp"
#include "handshake.hpp"
#include "timer.hpp"
@@ -1975,10 +1976,10 @@ X509_NAME* X509::GetSubject()
} // namespace
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
namespace mySTL {
-template yaSSL::yassl_int_cpp_local1::SumData mySTL::for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData);
-template yaSSL::yassl_int_cpp_local1::SumBuffer mySTL::for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer);
-template mySTL::list<yaSSL::SSL_SESSION*>::iterator mySTL::find_if<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match);
+template yaSSL::yassl_int_cpp_local1::SumData for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData);
+template yaSSL::yassl_int_cpp_local1::SumBuffer for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer);
+template mySTL::list<yaSSL::SSL_SESSION*>::iterator find_if<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match);
}
#endif
diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp
index 812cdd93879..187d5cc6769 100644
--- a/extra/yassl/taocrypt/include/misc.hpp
+++ b/extra/yassl/taocrypt/include/misc.hpp
@@ -30,14 +30,9 @@
#include "types.hpp"
#include "type_traits.hpp"
-/*
-namespace GCC_ABI {
- extern "C" int __cxa_pure_virtual();
-} */
-namespace TaoCrypt {
-// using GCC_ABI::__cxa_pure_virtual;
+namespace TaoCrypt {
// library allocation
struct new_t {}; // TaoCrypt New type
@@ -75,7 +70,7 @@ void tcArrayDelete(T* ptr)
// to resolve compiler generated operator delete on base classes with
-// virtual destructors, make sure doesn't get called
+// virtual destructors (when on stack), make sure doesn't get called
class virtual_base {
public:
static void operator delete(void*) { assert(0); }
@@ -742,8 +737,6 @@ unsigned int BytePrecision(unsigned long value);
unsigned int BitPrecision(unsigned long);
unsigned long Crop(unsigned long value, unsigned int size);
-void CallNewHandler();
-
} // namespace
diff --git a/extra/yassl/taocrypt/include/random.hpp b/extra/yassl/taocrypt/include/random.hpp
index 5fdda8da47a..62f49a8716f 100644
--- a/extra/yassl/taocrypt/include/random.hpp
+++ b/extra/yassl/taocrypt/include/random.hpp
@@ -42,7 +42,7 @@ public:
void GenerateSeed(byte*, word32 sz);
Error GetError() const { return error_; }
private:
-#if defined(WIN32)
+#if defined(_WIN32)
#if defined(_WIN64)
typedef unsigned __int64 ProviderHandle;
// type HCRYPTPROV, avoid #include <windows.h>
diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp
index 01106b6f960..f506040f0d8 100644
--- a/extra/yassl/taocrypt/include/runtime.hpp
+++ b/extra/yassl/taocrypt/include/runtime.hpp
@@ -25,7 +25,7 @@
-#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__)
+#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__) && !defined(__ICC)
#define yaSSL_NEW_HPP
@@ -34,6 +34,8 @@
extern "C" {
#include <assert.h>
+/* Disallow inline __cxa_pure_virtual() */
+static int __cxa_pure_virtual() __attribute__((noinline, used));
static int __cxa_pure_virtual()
{
// oops, pure virtual called!
diff --git a/extra/yassl/taocrypt/include/types.hpp b/extra/yassl/taocrypt/include/types.hpp
index 9c5d3e4b194..18961cf4d6f 100644
--- a/extra/yassl/taocrypt/include/types.hpp
+++ b/extra/yassl/taocrypt/include/types.hpp
@@ -25,6 +25,10 @@
#ifndef TAO_CRYPT_TYPES_HPP
#define TAO_CRYPT_TYPES_HPP
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
namespace TaoCrypt {
// define this if running on a big-endian CPU
@@ -80,16 +84,14 @@ typedef unsigned int word32;
#else
#define TAOCRYPT_NATIVE_DWORD_AVAILABLE
#ifdef WORD64_AVAILABLE
- #define TAOCRYPT_SLOW_WORD64
- // define this if your CPU is not64-bit to use alternative code
- // that avoids word64
- typedef word16 hword;
- typedef word32 word;
- typedef word64 dword;
+ #define TAOCRYPT_SLOW_WORD64
+ typedef word16 hword;
+ typedef word32 word;
+ typedef word64 dword;
#else
- typedef byte hword;
- typedef word16 word;
- typedef word32 dword;
+ typedef byte hword;
+ typedef word16 word;
+ typedef word32 dword;
#endif
#endif
diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp
index 7608e78b0ed..e0472f2fc76 100644
--- a/extra/yassl/taocrypt/src/algebra.cpp
+++ b/extra/yassl/taocrypt/src/algebra.cpp
@@ -319,7 +319,7 @@ void AbstractRing::SimultaneousExponentiate(Integer *results,
} // namespace
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
namespace mySTL {
template TaoCrypt::WindowSlider* uninit_copy<TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
template void destroy<TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
index 720fe7cd532..8f8d2ba52da 100644
--- a/extra/yassl/taocrypt/src/asn.cpp
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -22,7 +22,6 @@
/* asn.cpp implements ASN1 BER, PublicKey, and x509v3 decoding
*/
-
#include "runtime.hpp"
#include "asn.hpp"
#include "file.hpp"
diff --git a/extra/yassl/taocrypt/src/dh.cpp b/extra/yassl/taocrypt/src/dh.cpp
index d5f93f6c0f6..ea1b5846f7d 100644
--- a/extra/yassl/taocrypt/src/dh.cpp
+++ b/extra/yassl/taocrypt/src/dh.cpp
@@ -23,6 +23,7 @@
/* dh.cpp implements Diffie-Hellman support
*/
+#include "runtime.hpp"
#include "dh.hpp"
#include "asn.hpp"
diff --git a/extra/yassl/taocrypt/src/dsa.cpp b/extra/yassl/taocrypt/src/dsa.cpp
index e0d0519c169..4574fe5ebd8 100644
--- a/extra/yassl/taocrypt/src/dsa.cpp
+++ b/extra/yassl/taocrypt/src/dsa.cpp
@@ -20,6 +20,7 @@
*/
+#include "runtime.hpp"
#include "dsa.hpp"
#include "sha.hpp"
#include "asn.hpp"
diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp
index 0f06b9805dd..460b2d31426 100644
--- a/extra/yassl/taocrypt/src/integer.cpp
+++ b/extra/yassl/taocrypt/src/integer.cpp
@@ -23,6 +23,7 @@
/* based on Wei Dai's integer.cpp from CryptoPP */
+#include "runtime.hpp"
#include "integer.hpp"
#include "modarith.hpp"
#include "asn.hpp"
@@ -34,6 +35,22 @@
#endif
+#if defined(_MSC_VER) && defined(_WIN64) && \
+ !defined(__INTEL_COMPILER) // 64 bit X overflow intrinsic
+ #ifdef __ia64__
+ #define myUMULH __UMULH
+ #elif __x86_64__
+ #define myUMULH __umulh
+ #else
+ #error unknown 64bit windows
+ #endif
+
+extern "C" word myUMULH(word, word);
+
+#pragma intrinsic (myUMULH)
+#endif
+
+
#ifdef SSE2_INTRINSICS_AVAILABLE
#ifdef __GNUC__
#include <xmmintrin.h>
@@ -73,16 +90,15 @@ CPP_TYPENAME AllocatorBase<T>::pointer AlignedAllocator<T>::allocate(
{
void* p;
#ifdef TAOCRYPT_MM_MALLOC_AVAILABLE
- while (!(p = _mm_malloc(sizeof(T)*n, 16)))
+ p = _mm_malloc(sizeof(T)*n, 16);
#elif defined(TAOCRYPT_MEMALIGN_AVAILABLE)
- while (!(p = memalign(16, sizeof(T)*n)))
+ p = memalign(16, sizeof(T)*n);
#elif defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16)
- while (!(p = malloc(sizeof(T)*n)))
+ p = malloc(sizeof(T)*n);
#else
- while (!(p = (byte *)malloc(sizeof(T)*n + 8)))
+ p = (byte *)malloc(sizeof(T)*n + 8);
// assume malloc alignment is at least 8
#endif
- CallNewHandler();
#ifdef TAOCRYPT_NO_ALIGNED_ALLOC
assert(m_pBlock == 0);
@@ -156,8 +172,14 @@ DWord() {}
static DWord Multiply(word a, word b)
{
DWord r;
+
#ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
r.whole_ = (dword)a * b;
+
+ #elif defined(_MSC_VER)
+ r.halfs_.low = a*b;
+ r.halfs_.high = myUMULH(a,b);
+
#elif defined(__alpha__)
r.halfs_.low = a*b;
#ifdef __GNUC__
@@ -166,22 +188,27 @@ DWord() {}
#elif defined(__DECCXX)
r.halfs_.high = asm("umulh %a0, %a1, %v0", a, b);
#else
- #error can not implement multiply overflow
+ #error unknown alpha compiler
#endif
+
#elif defined(__ia64__)
r.halfs_.low = a*b;
__asm__("xmpy.hu %0=%1,%2" : "=f" (r.halfs_.high)
: "f" (a), "f" (b));
+
#elif defined(_ARCH_PPC64)
r.halfs_.low = a*b;
__asm__("mulhdu %0,%1,%2" : "=r" (r.halfs_.high)
: "r" (a), "r" (b) : "cc");
+
#elif defined(__x86_64__)
__asm__("mulq %3" : "=d" (r.halfs_.high), "=a" (r.halfs_.low) :
"a" (a), "rm" (b) : "cc");
+
#elif defined(__mips64)
__asm__("dmultu %2,%3" : "=h" (r.halfs_.high), "=l" (r.halfs_.low)
: "r" (a), "r" (b));
+
#elif defined(_M_IX86)
// for testing
word64 t = (word64)a * b;
@@ -190,6 +217,7 @@ DWord() {}
#else
#error can not implement DWord
#endif
+
return r;
}
@@ -3929,12 +3957,13 @@ Integer CRT(const Integer &xp, const Integer &p, const Integer &xq,
return p * (u * (xq-xp) % q) + xp;
}
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
#ifndef TAOCRYPT_NATIVE_DWORD_AVAILABLE
template hword DivideThreeWordsByTwo<hword, Word>(hword*, hword, hword, Word*);
#endif
template word DivideThreeWordsByTwo<word, DWord>(word*, word, word, DWord*);
#endif
+
} // namespace
diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp
index 6d43273ef20..6a801a9995a 100644
--- a/extra/yassl/taocrypt/src/misc.cpp
+++ b/extra/yassl/taocrypt/src/misc.cpp
@@ -64,10 +64,6 @@ void* operator new[](size_t sz);
void operator delete[](void* ptr);
*/
-/* namespace GCC_ABI {
- extern "C" int __cxa_pure_virtual() { assert(0); return 0; }
-} */
-
namespace TaoCrypt {
@@ -135,17 +131,5 @@ unsigned long Crop(unsigned long value, unsigned int size)
}
-#if !(defined(_MSC_VER) && (_MSC_VER < 1300)) && \
- !(defined(__HP_aCC) && (__HP_aCC <= 35700))
-using std::new_handler;
-using std::set_new_handler;
-#endif
-
-void CallNewHandler()
-{
- abort();
-}
-
-
} // namespace
diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp
index 921e710540d..69fb180720a 100644
--- a/extra/yassl/taocrypt/src/random.cpp
+++ b/extra/yassl/taocrypt/src/random.cpp
@@ -26,7 +26,7 @@
#include "random.hpp"
-#if defined(WIN32)
+#if defined(_WIN32)
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <wincrypt.h>
@@ -34,7 +34,7 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
-#endif // WIN32
+#endif // _WIN32
namespace TaoCrypt {
@@ -64,7 +64,7 @@ byte RandomNumberGenerator::GenerateByte()
}
-#if defined(WIN32)
+#if defined(_WIN32)
OS_Seed::OS_Seed()
{
@@ -87,7 +87,7 @@ void OS_Seed::GenerateSeed(byte* output, word32 sz)
}
-#else // WIN32
+#else // _WIN32
OS_Seed::OS_Seed()
@@ -122,7 +122,7 @@ void OS_Seed::GenerateSeed(byte* output, word32 sz)
}
}
-#endif // WIN32
+#endif // _WIN32
diff --git a/extra/yassl/taocrypt/src/rsa.cpp b/extra/yassl/taocrypt/src/rsa.cpp
index 4c7c45b8ffe..021fd992b5c 100644
--- a/extra/yassl/taocrypt/src/rsa.cpp
+++ b/extra/yassl/taocrypt/src/rsa.cpp
@@ -21,6 +21,7 @@
/* based on Wei Dai's rsa.cpp from CryptoPP */
+#include "runtime.hpp"
#include "rsa.hpp"
#include "asn.hpp"
#include "modarith.hpp"
diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp
index 81a8273c5c3..28994282669 100644
--- a/extra/yassl/taocrypt/src/template_instnt.cpp
+++ b/extra/yassl/taocrypt/src/template_instnt.cpp
@@ -4,7 +4,7 @@
#include "vector.hpp"
#include "hash.hpp"
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
namespace TaoCrypt {
#if defined(SSE2_INTRINSICS_AVAILABLE)
template AlignedAllocator<unsigned int>::pointer StdReallocate<unsigned int, AlignedAllocator<unsigned int> >(AlignedAllocator<unsigned int>&, unsigned int*, AlignedAllocator<unsigned int>::size_type, AlignedAllocator<unsigned int>::size_type, bool);
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index 7f02eb587a8..9e4636ebdc0 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -778,7 +778,7 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
key+= seg->length;
}
memcpy(key, &recpos, sizeof(byte*));
- return key - start_key;
+ return (uint) (key - start_key);
}
@@ -844,7 +844,7 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
key+= seg->length;
k_len-= seg->length;
}
- return key - start_key;
+ return (uint) (key - start_key);
}
@@ -866,7 +866,7 @@ uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
continue;
key+= seg->length;
}
- return key - start_key;
+ return (uint) (key - start_key);
}
@@ -886,7 +886,7 @@ uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key)
}
key+= length;
}
- return key - start_key;
+ return (uint) (key - start_key);
}
diff --git a/heap/hp_update.c b/heap/hp_update.c
index 2f4ea75f9aa..63ada225f06 100644
--- a/heap/hp_update.c
+++ b/heap/hp_update.c
@@ -60,7 +60,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
err:
if (my_errno == HA_ERR_FOUND_DUPP_KEY)
{
- info->errkey = keydef - share->keydef;
+ info->errkey = (int) (keydef - share->keydef);
if (keydef->algorithm == HA_KEY_ALG_BTREE)
{
/* we don't need to delete non-inserted key from rb-tree */
diff --git a/include/config-netware.h b/include/config-netware.h
index 4a6dc3b1bb9..906f557f608 100644
--- a/include/config-netware.h
+++ b/include/config-netware.h
@@ -46,11 +46,21 @@ extern "C" {
#undef HAVE_SYS_MMAN_H
#undef HAVE_SYNCH_H
#undef HAVE_MMAP
+
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
#define HAVE_PTHREAD_SIGMASK 1
#define HAVE_PTHREAD_YIELD_ZERO_ARG 1
#define HAVE_BROKEN_REALPATH 1
+#undef HAVE_POSIX_SIGNALS
+#undef HAVE_PTHREAD_ATTR_SETSCOPE
+#undef HAVE_ALLOC_A
+#undef HAVE_FINITE
+#undef HAVE_GETPWNAM
+#undef HAVE_GETPWUID
+#undef HAVE_PTHREAD_SETSCHEDPARAM
+#undef HAVE_READLINK
+#undef HAVE_STPCPY
/* no libc crypt() function */
#ifdef HAVE_OPENSSL
#define HAVE_CRYPT 1
diff --git a/include/my_base.h b/include/my_base.h
index 25fa683744e..c76cf8c604e 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -367,6 +367,7 @@ enum ha_base_keytype {
#define HA_STATE_EXTEND_BLOCK 2048
#define HA_STATE_RNEXT_SAME 4096 /* rnext_same was called */
+/* myisampack expects no more than 32 field types. */
enum en_fieldtype {
FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE,
FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO,
diff --git a/include/my_global.h b/include/my_global.h
index 04d33be38b4..22ec6dfffd3 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -295,10 +295,8 @@ C_MODE_END
#include <alloca.h>
#endif
#ifdef HAVE_ATOMIC_ADD
-#if defined(__ia64__)
#define new my_arg_new
#define need_to_restore_new 1
-#endif
C_MODE_START
#include <asm/atomic.h>
C_MODE_END
diff --git a/include/mysql_com.h b/include/mysql_com.h
index c608a2e7724..2293476c76c 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -48,8 +48,8 @@ enum enum_server_command
COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING,
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
- COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT,
- COM_RESET_STMT, COM_SET_OPTION, COM_FETCH,
+ COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE,
+ COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH,
/* don't forget to update const char *command_name[] in sql_parse.cc */
/* Must be last */
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index 1744fc36f4d..c27fb73ff8d 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -20,6 +20,7 @@ Created 6/2/1994 Heikki Tuuri
#include "rem0cmp.h"
#include "lock0lock.h"
#include "ibuf0ibuf.h"
+#include "trx0trx.h"
/*
Latching strategy of the InnoDB B-tree
@@ -137,13 +138,13 @@ btr_root_get(
ulint space;
ulint root_page_no;
page_t* root;
- ibool comp = UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp;
space = dict_tree_get_space(tree);
root_page_no = dict_tree_get_page(tree);
root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
- ut_a(page_is_comp(root) == comp);
+ ut_a((ibool)!!page_is_comp(root) ==
+ UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
return(root);
}
@@ -163,21 +164,19 @@ btr_get_prev_user_rec(
page_t* page;
page_t* prev_page;
ulint prev_page_no;
- rec_t* prev_rec;
ulint space;
- page = buf_frame_align(rec);
-
- if (page_get_infimum_rec(page) != rec) {
+ if (!page_rec_is_infimum(rec)) {
- prev_rec = page_rec_get_prev(rec);
+ rec_t* prev_rec = page_rec_get_prev(rec);
- if (page_get_infimum_rec(page) != prev_rec) {
+ if (!page_rec_is_infimum(prev_rec)) {
return(prev_rec);
}
}
+ page = buf_frame_align(rec);
prev_page_no = btr_page_get_prev(page, mtr);
space = buf_frame_get_space_id(page);
@@ -192,9 +191,7 @@ btr_get_prev_user_rec(
MTR_MEMO_PAGE_X_FIX)));
ut_a(page_is_comp(prev_page) == page_is_comp(page));
- prev_rec = page_rec_get_prev(page_get_supremum_rec(prev_page));
-
- return(prev_rec);
+ return(page_rec_get_prev(page_get_supremum_rec(prev_page)));
}
return(NULL);
@@ -215,21 +212,19 @@ btr_get_next_user_rec(
page_t* page;
page_t* next_page;
ulint next_page_no;
- rec_t* next_rec;
ulint space;
- page = buf_frame_align(rec);
-
- if (page_get_supremum_rec(page) != rec) {
+ if (!page_rec_is_supremum(rec)) {
- next_rec = page_rec_get_next(rec);
+ rec_t* next_rec = page_rec_get_next(rec);
- if (page_get_supremum_rec(page) != next_rec) {
+ if (!page_rec_is_supremum(next_rec)) {
return(next_rec);
}
}
+ page = buf_frame_align(rec);
next_page_no = btr_page_get_next(page, mtr);
space = buf_frame_get_space_id(page);
@@ -244,9 +239,7 @@ btr_get_next_user_rec(
MTR_MEMO_PAGE_X_FIX)));
ut_a(page_is_comp(next_page) == page_is_comp(page));
- next_rec = page_rec_get_next(page_get_infimum_rec(next_page));
-
- return(next_rec);
+ return(page_rec_get_next(page_get_infimum_rec(next_page)));
}
return(NULL);
@@ -573,8 +566,7 @@ btr_page_get_father_for_rec(
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
- ut_a(user_rec != page_get_supremum_rec(page));
- ut_a(user_rec != page_get_infimum_rec(page));
+ ut_a(page_rec_is_user_rec(user_rec));
ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page));
@@ -598,6 +590,7 @@ btr_page_get_father_for_rec(
if (btr_node_ptr_get_child_page_no(node_ptr, offsets) !=
buf_frame_get_page_no(page)) {
+ rec_t* print_rec;
fputs("InnoDB: Dump of the child page:\n", stderr);
buf_page_print(buf_frame_align(page));
fputs("InnoDB: Dump of the parent page:\n", stderr);
@@ -612,11 +605,10 @@ btr_page_get_father_for_rec(
(ulong)
btr_node_ptr_get_child_page_no(node_ptr, offsets),
(ulong) buf_frame_get_page_no(page));
- offsets = rec_get_offsets(page_rec_get_next(
- page_get_infimum_rec(page)), index,
+ print_rec = page_rec_get_next(page_get_infimum_rec(page));
+ offsets = rec_get_offsets(print_rec, index,
offsets, ULINT_UNDEFINED, &heap);
- page_rec_print(page_rec_get_next(page_get_infimum_rec(page)),
- offsets);
+ page_rec_print(print_rec, offsets);
offsets = rec_get_offsets(node_ptr, index, offsets,
ULINT_UNDEFINED, &heap);
page_rec_print(node_ptr, offsets);
@@ -663,7 +655,7 @@ btr_create(
ulint type, /* in: type of the index */
ulint space, /* in: space where created */
dulint index_id,/* in: index id */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr) /* in: mini-transaction handle */
{
ulint page_no;
@@ -854,11 +846,12 @@ btr_page_reorganize_low(
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
+ ut_ad(!!page_is_comp(page) == index->table->comp);
data_size1 = page_get_data_size(page);
max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1);
/* Write the log record */
- mlog_open_and_write_index(mtr, page, index, index->table->comp
+ mlog_open_and_write_index(mtr, page, index, page_is_comp(page)
? MLOG_COMP_PAGE_REORGANIZE
: MLOG_PAGE_REORGANIZE, 0);
@@ -877,7 +870,7 @@ btr_page_reorganize_low(
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
- page_create(page, mtr, index->table->comp);
+ page_create(page, mtr, page_is_comp(page));
buf_block_align(page)->check_index_page_at_flush = TRUE;
/* Copy the records from the temporary space to the recreated page;
@@ -1070,7 +1063,7 @@ btr_root_raise_and_insert(
as there is no lower alphabetical limit to records in the leftmost
node of a level: */
- btr_set_min_rec_mark(node_ptr_rec, cursor->index->table->comp, mtr);
+ btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr);
/* Free the memory heap */
mem_heap_free(heap);
@@ -1151,7 +1144,6 @@ btr_page_get_split_rec_to_right(
{
page_t* page;
rec_t* insert_point;
- rec_t* supremum;
page = btr_cur_get_page(cursor);
insert_point = btr_cur_get_rec(cursor);
@@ -1160,13 +1152,23 @@ btr_page_get_split_rec_to_right(
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) {
+ if (UNIV_LIKELY(page_header_get_ptr(page, PAGE_LAST_INSERT)
+ == insert_point)) {
+
+ rec_t* next_rec;
+
+ next_rec = page_rec_get_next(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) {
+ if (page_rec_is_supremum(next_rec)) {
+split_at_new:
+ /* Split at the new record to insert */
+ *split_rec = NULL;
+ } else {
+ rec_t* next_next_rec = page_rec_get_next(next_rec);
+ if (page_rec_is_supremum(next_next_rec)) {
+
+ goto split_at_new;
+ }
/* If there are >= 2 user records up from the insert
point, split all but 1 off. We want to keep one because
@@ -1175,12 +1177,8 @@ btr_page_get_split_rec_to_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 the new record to insert */
- *split_rec = NULL;
- }
+ *split_rec = next_next_rec;
+ }
return(TRUE);
}
@@ -1220,7 +1218,7 @@ btr_page_get_sure_split_rec(
page = btr_cur_get_page(cursor);
insert_size = rec_get_converted_size(cursor->index, tuple);
- free_space = page_get_free_space_of_empty(cursor->index->table->comp);
+ free_space = page_get_free_space_of_empty(page_is_comp(page));
/* free_space is now the free space of a created new page */
@@ -1276,21 +1274,22 @@ btr_page_get_sure_split_rec(
supremum record of page */
if (rec == ins_rec) {
- next_rec = NULL;
+ rec = NULL;
+
+ goto func_exit;
} else if (rec == NULL) {
next_rec = page_rec_get_next(ins_rec);
} else {
next_rec = page_rec_get_next(rec);
}
- if (next_rec != page_get_supremum_rec(page)) {
- if (heap) {
- mem_heap_free(heap);
- }
- return(next_rec);
+ ut_ad(next_rec);
+ if (!page_rec_is_supremum(next_rec)) {
+ rec = next_rec;
}
}
- if (heap) {
+func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(rec);
@@ -1329,13 +1328,12 @@ btr_page_insert_fits(
ut_ad(!split_rec == !offsets);
ut_ad(!offsets
- || cursor->index->table->comp == rec_offs_comp(offsets));
+ || !page_is_comp(page) == !rec_offs_comp(offsets));
ut_ad(!offsets
|| rec_offs_validate(split_rec, cursor->index, offsets));
- ut_ad(page_is_comp(page) == cursor->index->table->comp);
insert_size = rec_get_converted_size(cursor->index, tuple);
- free_space = page_get_free_space_of_empty(cursor->index->table->comp);
+ free_space = page_get_free_space_of_empty(page_is_comp(page));
/* free_space is now the free space of a created new page */
@@ -1832,14 +1830,15 @@ void
btr_set_min_rec_mark_log(
/*=====================*/
rec_t* rec, /* in: record */
- ibool comp, /* TRUE=compact record format */
+ ulint comp, /* nonzero=compact record format */
mtr_t* mtr) /* in: mtr */
{
mlog_write_initial_log_record(rec,
comp ? MLOG_COMP_REC_MIN_MARK : MLOG_REC_MIN_MARK, mtr);
/* Write rec offset as a 2-byte ulint */
- mlog_catenate_ulint(mtr, rec - buf_frame_align(rec), MLOG_2BYTES);
+ mlog_catenate_ulint(mtr, ut_align_offset(rec, UNIV_PAGE_SIZE),
+ MLOG_2BYTES);
}
/********************************************************************
@@ -1852,7 +1851,7 @@ btr_parse_set_min_rec_mark(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -1864,6 +1863,8 @@ btr_parse_set_min_rec_mark(
}
if (page) {
+ ut_a(!page_is_comp(page) == !comp);
+
rec = page + mach_read_from_2(ptr);
btr_set_min_rec_mark(rec, comp, mtr);
@@ -1879,7 +1880,7 @@ void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr) /* in: mtr */
{
ulint info_bits;
@@ -2008,11 +2009,12 @@ btr_compress(
ulint max_ins_size;
ulint max_ins_size_reorg;
ulint level;
- ibool comp = cursor->index->table->comp;
+ ulint comp;
page = btr_cur_get_page(cursor);
tree = btr_cur_get_tree(cursor);
- ut_a(comp == page_is_comp(page));
+ comp = page_is_comp(page);
+ ut_a((ibool)!!comp == cursor->index->table->comp);
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
@@ -2055,7 +2057,7 @@ btr_compress(
n_recs = page_get_n_recs(page);
data_size = page_get_data_size(page);
- ut_a(page_is_comp(merge_page) == page_is_comp(page));
+ ut_a(page_is_comp(merge_page) == comp);
max_ins_size_reorg = page_get_max_insert_size_after_reorganize(
merge_page, n_recs);
@@ -2108,7 +2110,7 @@ btr_compress(
rec_get_offsets(node_ptr, cursor->index,
offsets_, ULINT_UNDEFINED, &heap),
right_page_no, mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
btr_node_ptr_delete(tree, merge_page, mtr);
@@ -2250,10 +2252,9 @@ btr_discard_page(
node_ptr = page_rec_get_next(page_get_infimum_rec(merge_page));
- ut_ad(node_ptr != page_get_supremum_rec(merge_page));
+ ut_ad(page_rec_is_user_rec(node_ptr));
- btr_set_min_rec_mark(node_ptr,
- cursor->index->table->comp, mtr);
+ btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr);
}
btr_node_ptr_delete(tree, page, mtr);
@@ -2274,6 +2275,7 @@ btr_discard_page(
ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
}
+#ifdef UNIV_BTR_PRINT
/*****************************************************************
Prints size info of a B-tree. */
@@ -2401,14 +2403,15 @@ btr_print_tree(
root = btr_root_get(tree, &mtr);
btr_print_recursive(tree, root, width, &heap, &offsets, &mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
mtr_commit(&mtr);
- btr_validate_tree(tree);
+ btr_validate_tree(tree, NULL);
}
+#endif /* UNIV_BTR_PRINT */
/****************************************************************
Checks that the node pointer to a page is appropriate. */
@@ -2496,8 +2499,8 @@ btr_index_rec_validate(
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
page = buf_frame_align(rec);
-
- if (index->type & DICT_UNIVERSAL) {
+
+ if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
/* The insert buffer index tree can contain records from any
other index: we cannot check the number of fields or
their length */
@@ -2505,9 +2508,18 @@ btr_index_rec_validate(
return(TRUE);
}
+ if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) != index->table->comp)) {
+ btr_index_rec_validate_report(page, rec, index);
+ fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n",
+ (ulong) !!page_is_comp(page),
+ (ulong) index->table->comp);
+ return(FALSE);
+ }
+
n = dict_index_get_n_fields(index);
- if (!index->table->comp && rec_get_n_fields_old(rec) != n) {
+ if (!page_is_comp(page)
+ && UNIV_UNLIKELY(rec_get_n_fields_old(rec) != n)) {
btr_index_rec_validate_report(page, rec, index);
fprintf(stderr, "InnoDB: has %lu fields, should have %lu\n",
(ulong) rec_get_n_fields_old(rec), (ulong) n);
@@ -2554,14 +2566,14 @@ btr_index_rec_validate(
rec_print_new(stderr, rec, offsets);
putc('\n', stderr);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(FALSE);
}
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(TRUE);
@@ -2649,6 +2661,7 @@ btr_validate_level(
/*===============*/
/* out: TRUE if ok */
dict_tree_t* tree, /* in: index tree */
+ trx_t* trx, /* in: transaction or NULL */
ulint level) /* in: level number */
{
ulint space;
@@ -2696,6 +2709,11 @@ btr_validate_level(
/* Now we are on the desired level. Loop through the pages on that
level. */
loop:
+ if (trx_is_interrupted(trx)) {
+ mtr_commit(&mtr);
+ mem_heap_free(heap);
+ return(ret);
+ }
mem_heap_empty(heap);
offsets = offsets2 = NULL;
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
@@ -2765,7 +2783,7 @@ loop:
if (level > 0 && left_page_no == FIL_NULL) {
ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
page_rec_get_next(page_get_infimum_rec(page)),
- index->table->comp));
+ page_is_comp(page)));
}
if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) {
@@ -2921,7 +2939,7 @@ node_ptr_fails:
mtr_commit(&mtr);
if (right_page_no != FIL_NULL) {
- ibool comp = page_is_comp(page);
+ ulint comp = page_is_comp(page);
mtr_start(&mtr);
page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr);
@@ -2941,7 +2959,8 @@ ibool
btr_validate_tree(
/*==============*/
/* out: TRUE if ok */
- dict_tree_t* tree) /* in: tree */
+ dict_tree_t* tree, /* in: tree */
+ trx_t* trx) /* in: transaction or NULL */
{
mtr_t mtr;
page_t* root;
@@ -2954,9 +2973,8 @@ btr_validate_tree(
root = btr_root_get(tree, &mtr);
n = btr_page_get_level(root, &mtr);
- for (i = 0; i <= n; i++) {
-
- if (!btr_validate_level(tree, n - i)) {
+ for (i = 0; i <= n && !trx_is_interrupted(trx); i++) {
+ if (!btr_validate_level(tree, trx, n - i)) {
mtr_commit(&mtr);
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index e093c911f22..30e85e021bc 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -36,11 +36,11 @@ Created 10/16/1994 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "lock0lock.h"
+#ifdef UNIV_DEBUG
/* If the following is set to TRUE, this module prints a lot of
trace information of individual record operations */
ibool btr_cur_print_record_ops = FALSE;
-
-ulint btr_cur_rnd = 0;
+#endif /* UNIV_DEBUG */
ulint btr_cur_n_non_sea = 0;
ulint btr_cur_n_sea = 0;
@@ -431,7 +431,7 @@ retry_page_get:
cursor->thr)) {
/* Insertion to the insert buffer succeeded */
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return;
@@ -505,8 +505,9 @@ retry_page_get:
if (level > 0) {
/* x-latch the page */
- ut_a(page_is_comp(btr_page_get(space,
- page_no, RW_X_LATCH, mtr))
+ page = btr_page_get(space,
+ page_no, RW_X_LATCH, mtr);
+ ut_a((ibool)!!page_is_comp(page)
== index->table->comp);
}
@@ -525,7 +526,7 @@ retry_page_get:
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -681,7 +682,7 @@ btr_cur_open_at_index_side(
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -762,7 +763,7 @@ btr_cur_open_at_rnd_pos(
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -879,6 +880,7 @@ btr_cur_ins_lock_and_undo(
return(DB_SUCCESS);
}
+#ifdef UNIV_DEBUG
/*****************************************************************
Report information about a transaction. */
static
@@ -896,6 +898,7 @@ btr_cur_trx_report(
dict_index_name_print(stderr, trx, index);
putc('\n', stderr);
}
+#endif /* UNIV_DEBUG */
/*****************************************************************
Tries to perform an insert to a page in an index tree, next to cursor.
@@ -945,12 +948,13 @@ btr_cur_optimistic_insert(
fputs("InnoDB: Error in a tuple to insert into ", stderr);
dict_index_name_print(stderr, thr_get_trx(thr), index);
}
-
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "insert into ");
dtuple_print(stderr, entry);
}
-
+#endif /* UNIV_DEBUG */
+
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
max_size = page_get_max_insert_size_after_reorganize(page, 1);
@@ -961,7 +965,7 @@ calculate_sizes_again:
rec_size = rec_get_converted_size(index, entry);
if (rec_size >=
- ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
+ ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
REC_MAX_DATA_SIZE)) {
/* The record is so big that we have to store some fields
@@ -1027,7 +1031,7 @@ calculate_sizes_again:
*rec = page_cur_insert_rec_low(page_cursor, entry, index,
NULL, NULL, mtr);
- if (!(*rec)) {
+ if (UNIV_UNLIKELY(!(*rec))) {
/* If the record did not fit, reorganize */
btr_page_reorganize(page, index, mtr);
@@ -1039,7 +1043,7 @@ calculate_sizes_again:
*rec = page_cur_tuple_insert(page_cursor, entry, index, mtr);
- if (!*rec) {
+ if (UNIV_UNLIKELY(!*rec)) {
fputs("InnoDB: Error: cannot insert tuple ", stderr);
dtuple_print(stderr, entry);
fputs(" into ", stderr);
@@ -1166,7 +1170,7 @@ btr_cur_pessimistic_insert(
}
if (rec_get_converted_size(index, entry) >=
- ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
+ ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
REC_MAX_DATA_SIZE)) {
/* The record is so big that we have to store some fields
@@ -1261,7 +1265,7 @@ btr_cur_upd_lock_and_undo(
err = lock_clust_rec_modify_check_and_lock(flags, rec, index,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap), thr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
if (err != DB_SUCCESS) {
@@ -1293,9 +1297,11 @@ btr_cur_update_in_place_log(
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
+ page_t* page = ut_align_down(rec, UNIV_PAGE_SIZE);
ut_ad(flags < 256);
+ ut_ad(!!page_is_comp(page) == index->table->comp);
- log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
+ log_ptr = mlog_open_and_write_index(mtr, rec, index, page_is_comp(page)
? MLOG_COMP_REC_UPDATE_IN_PLACE
: MLOG_REC_UPDATE_IN_PLACE,
1 + DATA_ROLL_PTR_LEN + 14 + 2 + MLOG_BUF_MARGIN);
@@ -1317,7 +1323,7 @@ btr_cur_update_in_place_log(
log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
mtr);
- mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
log_ptr += 2;
row_upd_index_write_log(update, log_ptr, mtr);
@@ -1374,18 +1380,12 @@ btr_cur_parse_update_in_place(
ptr = row_upd_index_parse(ptr, end_ptr, heap, &update);
- if (ptr == NULL) {
- mem_heap_free(heap);
-
- return(NULL);
- }
-
- if (!page) {
- mem_heap_free(heap);
+ if (!ptr || !page) {
- return(ptr);
+ goto func_exit;
}
-
+
+ ut_a((ibool)!!page_is_comp(page) == index->table->comp);
rec = page + rec_offset;
/* We do not need to reserve btr_search_latch, as the page is only
@@ -1400,6 +1400,7 @@ btr_cur_parse_update_in_place(
row_upd_rec_in_place(rec, offsets, update);
+func_exit:
mem_heap_free(heap);
return(ptr);
@@ -1429,7 +1430,7 @@ btr_cur_update_in_place(
rec_t* rec;
dulint roll_ptr = ut_dulint_zero;
trx_t* trx;
- ibool was_delete_marked;
+ ulint was_delete_marked;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -1437,27 +1438,30 @@ btr_cur_update_in_place(
rec = btr_cur_get_rec(cursor);
index = cursor->index;
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
trx = thr_get_trx(thr);
- heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
-
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(trx, index, "update ");
rec_print_new(stderr, rec, offsets);
}
+#endif /* UNIV_DEBUG */
/* Do lock checking and undo logging */
err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info,
thr, &roll_ptr);
- if (err != DB_SUCCESS) {
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
}
block = buf_block_align(rec);
+ ut_ad(!!page_is_comp(buf_block_get_frame(block))
+ == index->table->comp);
if (block->is_hashed) {
/* The function row_upd_changes_ord_field_binary works only
@@ -1481,7 +1485,8 @@ btr_cur_update_in_place(
/* FIXME: in a mixed tree, all records may not have enough ordering
fields for btr search: */
- was_delete_marked = rec_get_deleted_flag(rec, index->table->comp);
+ was_delete_marked = rec_get_deleted_flag(rec,
+ page_is_comp(buf_block_get_frame(block)));
row_upd_rec_in_place(rec, offsets, update);
@@ -1491,14 +1496,15 @@ btr_cur_update_in_place(
btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr,
mtr);
- if (was_delete_marked && !rec_get_deleted_flag(rec, index->table->comp)) {
+ if (was_delete_marked && !rec_get_deleted_flag(rec,
+ page_is_comp(buf_block_get_frame(block)))) {
/* The new updated record owns its possible externally
stored fields */
btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(DB_SUCCESS);
@@ -1547,14 +1553,17 @@ btr_cur_optimistic_update(
page = btr_cur_get_page(cursor);
rec = btr_cur_get_rec(cursor);
index = cursor->index;
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "update ");
rec_print_new(stderr, rec, offsets);
}
+#endif /* UNIV_DEBUG */
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
@@ -1596,8 +1605,8 @@ btr_cur_optimistic_update(
old_rec_size = rec_offs_size(offsets);
new_rec_size = rec_get_converted_size(index, new_entry);
- if (new_rec_size >=
- page_get_free_space_of_empty(index->table->comp) / 2) {
+ if (UNIV_UNLIKELY(new_rec_size >= page_get_free_space_of_empty(
+ page_is_comp(page)) / 2)) {
mem_heap_free(heap);
@@ -1607,8 +1616,9 @@ btr_cur_optimistic_update(
max_size = old_rec_size
+ page_get_max_insert_size_after_reorganize(page, 1);
- if (page_get_data_size(page) - old_rec_size + new_rec_size
- < BTR_CUR_PAGE_COMPRESS_LIMIT) {
+ if (UNIV_UNLIKELY(page_get_data_size(page)
+ - old_rec_size + new_rec_size
+ < BTR_CUR_PAGE_COMPRESS_LIMIT)) {
/* The page would become too empty */
@@ -1644,7 +1654,7 @@ btr_cur_optimistic_update(
explicit locks on rec, before deleting rec (see the comment in
.._pessimistic_update). */
- lock_rec_store_on_page_infimum(rec);
+ lock_rec_store_on_page_infimum(page, rec);
btr_search_update_hash_on_delete(cursor);
@@ -1665,7 +1675,7 @@ btr_cur_optimistic_update(
ut_a(rec); /* <- We calculated above the insert would fit */
- if (!rec_get_deleted_flag(rec, index->table->comp)) {
+ if (!rec_get_deleted_flag(rec, page_is_comp(page))) {
/* The new inserted record owns its possible externally
stored fields */
@@ -1814,7 +1824,7 @@ btr_cur_pessimistic_update(
}
success = fsp_reserve_free_extents(&n_reserved,
- cursor->index->space,
+ index->space,
n_extents, reserve_flag, mtr);
if (!success) {
err = DB_OUT_OF_FILE_SPACE;
@@ -1858,14 +1868,14 @@ btr_cur_pessimistic_update(
ext_vect = mem_heap_alloc(heap, sizeof(ulint)
* dict_index_get_n_fields(index));
- ut_ad(!cursor->index->table->comp || !rec_get_node_ptr_flag(rec));
+ ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update);
- if (rec_get_converted_size(index, new_entry) >=
- ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
- REC_MAX_DATA_SIZE)) {
+ if (UNIV_UNLIKELY(rec_get_converted_size(index, new_entry) >=
+ ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
+ REC_MAX_DATA_SIZE))) {
big_rec_vec = dtuple_convert_big_rec(index, new_entry,
ext_vect, n_ext_vect);
@@ -1887,7 +1897,7 @@ btr_cur_pessimistic_update(
delete the lock structs set on the root page even if the root
page carries just node pointers. */
- lock_rec_store_on_page_infimum(rec);
+ lock_rec_store_on_page_infimum(buf_frame_align(rec), rec);
btr_search_update_hash_on_delete(cursor);
@@ -1965,8 +1975,7 @@ return_after_reservations:
mem_heap_free(heap);
if (n_extents > 0) {
- fil_space_release_free_extents(cursor->index->space,
- n_reserved);
+ fil_space_release_free_extents(index->space, n_reserved);
}
*big_rec = big_rec_vec;
@@ -1995,7 +2004,10 @@ btr_cur_del_mark_set_clust_rec_log(
ut_ad(flags < 256);
ut_ad(val <= 1);
- log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
+
+ log_ptr = mlog_open_and_write_index(mtr, rec, index,
+ page_rec_is_comp(rec)
? MLOG_COMP_REC_CLUST_DELETE_MARK
: MLOG_REC_CLUST_DELETE_MARK,
1 + 1 + DATA_ROLL_PTR_LEN + 14 + 2);
@@ -2012,7 +2024,7 @@ btr_cur_del_mark_set_clust_rec_log(
log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
mtr);
- mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
log_ptr += 2;
mlog_close(mtr, log_ptr);
@@ -2032,13 +2044,15 @@ btr_cur_parse_del_mark_set_clust_rec(
page_t* page) /* in: page or NULL */
{
ulint flags;
- ibool val;
+ ulint val;
ulint pos;
dulint trx_id;
dulint roll_ptr;
ulint offset;
rec_t* rec;
+ ut_ad(!page || !!page_is_comp(page) == index->table->comp);
+
if (end_ptr < ptr + 2) {
return(NULL);
@@ -2078,7 +2092,7 @@ btr_cur_parse_del_mark_set_clust_rec(
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
pos, trx_id, roll_ptr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -2087,7 +2101,7 @@ btr_cur_parse_del_mark_set_clust_rec(
is only being recovered, and there cannot be a hash index to
it. */
- rec_set_deleted_flag(rec, index->table->comp, val);
+ rec_set_deleted_flag(rec, page_is_comp(page), val);
}
return(ptr);
@@ -2123,22 +2137,25 @@ btr_cur_del_mark_set_clust_rec(
rec = btr_cur_get_rec(cursor);
index = cursor->index;
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "del mark ");
rec_print_new(stderr, rec, offsets);
}
+#endif /* UNIV_DEBUG */
ut_ad(index->type & DICT_CLUSTERED);
- ut_ad(rec_get_deleted_flag(rec, index->table->comp) == FALSE);
+ ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
err = lock_clust_rec_modify_check_and_lock(flags,
rec, index, offsets, thr);
if (err != DB_SUCCESS) {
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
@@ -2149,7 +2166,7 @@ btr_cur_del_mark_set_clust_rec(
&roll_ptr);
if (err != DB_SUCCESS) {
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
@@ -2161,7 +2178,7 @@ btr_cur_del_mark_set_clust_rec(
rw_lock_x_lock(&btr_search_latch);
}
- rec_set_deleted_flag(rec, index->table->comp, val);
+ rec_set_deleted_flag(rec, rec_offs_comp(offsets), val);
trx = thr_get_trx(thr);
@@ -2175,7 +2192,7 @@ btr_cur_del_mark_set_clust_rec(
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(DB_SUCCESS);
@@ -2189,17 +2206,13 @@ void
btr_cur_del_mark_set_sec_rec_log(
/*=============================*/
rec_t* rec, /* in: record */
- dict_index_t* index, /* in: record descriptor */
ibool val, /* in: value to set */
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
ut_ad(val <= 1);
- log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
- ? MLOG_COMP_REC_SEC_DELETE_MARK
- : MLOG_REC_SEC_DELETE_MARK,
- 1 + 2);
+ log_ptr = mlog_open(mtr, 11 + 1 + 2);
if (!log_ptr) {
/* Logging in mtr is switched off during crash recovery:
@@ -2207,10 +2220,12 @@ btr_cur_del_mark_set_sec_rec_log(
return;
}
+ log_ptr = mlog_write_initial_log_record_fast(
+ rec, MLOG_REC_SEC_DELETE_MARK, log_ptr, mtr);
mach_write_to_1(log_ptr, val);
log_ptr++;
- mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
log_ptr += 2;
mlog_close(mtr, log_ptr);
@@ -2226,10 +2241,9 @@ btr_cur_parse_del_mark_set_sec_rec(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
- dict_index_t* index, /* in: record descriptor */
page_t* page) /* in: page or NULL */
{
- ibool val;
+ ulint val;
ulint offset;
rec_t* rec;
@@ -2253,7 +2267,7 @@ btr_cur_parse_del_mark_set_sec_rec(
is only being recovered, and there cannot be a hash index to
it. */
- rec_set_deleted_flag(rec, index->table->comp, val);
+ rec_set_deleted_flag(rec, page_is_comp(page), val);
}
return(ptr);
@@ -2279,11 +2293,13 @@ btr_cur_del_mark_set_sec_rec(
rec = btr_cur_get_rec(cursor);
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), cursor->index,
"del mark ");
rec_print(stderr, rec, cursor->index);
}
+#endif /* UNIV_DEBUG */
err = lock_sec_rec_modify_check_and_lock(flags, rec, cursor->index,
thr);
@@ -2293,18 +2309,21 @@ btr_cur_del_mark_set_sec_rec(
}
block = buf_block_align(rec);
+ ut_ad(!!page_is_comp(buf_block_get_frame(block))
+ == cursor->index->table->comp);
if (block->is_hashed) {
rw_lock_x_lock(&btr_search_latch);
}
- rec_set_deleted_flag(rec, cursor->index->table->comp, val);
+ rec_set_deleted_flag(rec, page_is_comp(buf_block_get_frame(block)),
+ val);
if (block->is_hashed) {
rw_lock_x_unlock(&btr_search_latch);
}
- btr_cur_del_mark_set_sec_rec_log(rec, cursor->index, val, mtr);
+ btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
return(DB_SUCCESS);
}
@@ -2317,15 +2336,14 @@ void
btr_cur_del_unmark_for_ibuf(
/*========================*/
rec_t* rec, /* in: record to delete unmark */
- dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mtr */
{
/* We do not need to reserve btr_search_latch, as the page has just
been read to the buffer pool and there cannot be a hash index to it. */
- rec_set_deleted_flag(rec, index->table->comp, FALSE);
+ rec_set_deleted_flag(rec, page_is_comp(buf_frame_align(rec)), FALSE);
- btr_cur_del_mark_set_sec_rec_log(rec, index, FALSE, mtr);
+ btr_cur_del_mark_set_sec_rec_log(rec, FALSE, mtr);
}
/*==================== B-TREE RECORD REMOVE =========================*/
@@ -2444,7 +2462,7 @@ btr_cur_optimistic_delete(
mtr);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -2487,6 +2505,7 @@ btr_cur_pessimistic_delete(
ulint n_reserved;
ibool success;
ibool ret = FALSE;
+ ulint level;
mem_heap_t* heap;
ulint* offsets;
@@ -2523,15 +2542,15 @@ btr_cur_pessimistic_delete(
/* Free externally stored fields if the record is neither
a node pointer nor in two-byte format.
This avoids an unnecessary loop. */
- if (cursor->index->table->comp
+ if (page_is_comp(page)
? !rec_get_node_ptr_flag(rec)
: !rec_get_1byte_offs_flag(rec)) {
btr_rec_free_externally_stored_fields(cursor->index,
rec, offsets, in_rollback, mtr);
}
- if ((page_get_n_recs(page) < 2)
- && (dict_tree_get_page(btr_cur_get_tree(cursor))
+ if (UNIV_UNLIKELY(page_get_n_recs(page) < 2)
+ && UNIV_UNLIKELY(dict_tree_get_page(btr_cur_get_tree(cursor))
!= buf_frame_get_page_no(page))) {
/* If there is only one record, drop the whole page in
@@ -2546,9 +2565,13 @@ btr_cur_pessimistic_delete(
}
lock_update_delete(rec);
+ level = btr_page_get_level(page, mtr);
+
+ if (level > 0
+ && UNIV_UNLIKELY(rec == page_rec_get_next(
+ page_get_infimum_rec(page)))) {
- if ((btr_page_get_level(page, mtr) > 0)
- && (page_rec_get_next(page_get_infimum_rec(page)) == rec)) {
+ rec_t* next_rec = page_rec_get_next(rec);
if (btr_page_get_prev(page, mtr) == FIL_NULL) {
@@ -2556,8 +2579,8 @@ btr_cur_pessimistic_delete(
non-leaf level, we must mark the new leftmost node
pointer as the predefined minimum record */
- btr_set_min_rec_mark(page_rec_get_next(rec),
- cursor->index->table->comp, mtr);
+ btr_set_min_rec_mark(next_rec, page_is_comp(page),
+ mtr);
} else {
/* Otherwise, if we delete the leftmost node pointer
on a page, we have to change the father node pointer
@@ -2567,13 +2590,12 @@ btr_cur_pessimistic_delete(
btr_node_ptr_delete(tree, page, mtr);
node_ptr = dict_tree_build_node_ptr(
- tree, page_rec_get_next(rec),
+ tree, next_rec,
buf_frame_get_page_no(page),
- heap, btr_page_get_level(page, mtr));
+ heap, level);
btr_insert_on_non_leaf_level(tree,
- btr_page_get_level(page, mtr) + 1,
- node_ptr, mtr);
+ level + 1, node_ptr, mtr);
}
}
@@ -2813,24 +2835,24 @@ btr_estimate_number_of_different_key_vals(
ulint add_on;
mtr_t mtr;
mem_heap_t* heap = NULL;
- ulint offsets1_[REC_OFFS_NORMAL_SIZE];
- ulint offsets2_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets1 = offsets1_;
- ulint* offsets2 = offsets2_;
- *offsets1_ = (sizeof offsets1_) / sizeof *offsets1_;
- *offsets2_ = (sizeof offsets2_) / sizeof *offsets2_;
+ ulint offsets_rec_[REC_OFFS_NORMAL_SIZE];
+ ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets_rec = offsets_rec_;
+ ulint* offsets_next_rec= offsets_next_rec_;
+ *offsets_rec_ = (sizeof offsets_rec_) / sizeof *offsets_rec_;
+ *offsets_next_rec_ =
+ (sizeof offsets_next_rec_) / sizeof *offsets_next_rec_;
n_cols = dict_index_get_n_unique(index);
n_diff = mem_alloc((n_cols + 1) * sizeof(ib_longlong));
- for (j = 0; j <= n_cols; j++) {
- n_diff[j] = 0;
- }
+ memset(n_diff, 0, (n_cols + 1) * sizeof(ib_longlong));
/* We sample some pages in the index to get an estimate */
for (i = 0; i < BTR_KEY_VAL_ESTIMATE_N_PAGES; i++) {
+ rec_t* supremum;
mtr_start(&mtr);
btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
@@ -2843,26 +2865,29 @@ btr_estimate_number_of_different_key_vals(
page = btr_cur_get_page(&cursor);
- rec = page_get_infimum_rec(page);
- rec = page_rec_get_next(rec);
+ supremum = page_get_supremum_rec(page);
+ rec = page_rec_get_next(page_get_infimum_rec(page));
- if (rec != page_get_supremum_rec(page)) {
+ if (rec != supremum) {
not_empty_flag = 1;
+ offsets_rec = rec_get_offsets(rec, index, offsets_rec,
+ ULINT_UNDEFINED, &heap);
}
-
- while (rec != page_get_supremum_rec(page)
- && page_rec_get_next(rec)
- != page_get_supremum_rec(page)) {
+
+ while (rec != supremum) {
rec_t* next_rec = page_rec_get_next(rec);
+ if (next_rec == supremum) {
+ break;
+ }
+
matched_fields = 0;
matched_bytes = 0;
- offsets1 = rec_get_offsets(rec, index, offsets1,
- ULINT_UNDEFINED, &heap);
- offsets2 = rec_get_offsets(next_rec, index, offsets2,
+ offsets_next_rec = rec_get_offsets(next_rec, index,
+ offsets_next_rec,
n_cols, &heap);
cmp_rec_rec_with_match(rec, next_rec,
- offsets1, offsets2,
+ offsets_rec, offsets_next_rec,
index, &matched_fields,
&matched_bytes);
@@ -2875,9 +2900,17 @@ btr_estimate_number_of_different_key_vals(
total_external_size +=
btr_rec_get_externally_stored_len(
- rec, offsets1);
+ rec, offsets_rec);
- rec = page_rec_get_next(rec);
+ rec = next_rec;
+ /* Initialize offsets_rec for the next round
+ and assign the old offsets_rec buffer to
+ offsets_next_rec. */
+ {
+ ulint* offsets_tmp = offsets_rec;
+ offsets_rec = offsets_next_rec;
+ offsets_next_rec = offsets_tmp;
+ }
}
@@ -2899,11 +2932,11 @@ btr_estimate_number_of_different_key_vals(
}
}
- offsets1 = rec_get_offsets(rec, index, offsets1,
+ offsets_rec = rec_get_offsets(rec, index, offsets_rec,
ULINT_UNDEFINED, &heap);
total_external_size +=
btr_rec_get_externally_stored_len(rec,
- offsets1);
+ offsets_rec);
mtr_commit(&mtr);
}
@@ -2944,7 +2977,7 @@ btr_estimate_number_of_different_key_vals(
}
mem_free(n_diff);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -3599,7 +3632,7 @@ btr_rec_free_externally_stored_fields(
MTR_MEMO_PAGE_X_FIX));
/* Free possible externally stored fields in the record */
- ut_ad(index->table->comp == rec_offs_comp(offsets));
+ ut_ad(index->table->comp == !!rec_offs_comp(offsets));
n_fields = rec_offs_n_fields(offsets);
for (i = 0; i < n_fields; i++) {
diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c
index 74feff8653c..cb398b4afab 100644
--- a/innobase/btr/btr0pcur.c
+++ b/innobase/btr/btr0pcur.c
@@ -78,6 +78,7 @@ btr_pcur_store_position(
rec_t* rec;
dict_tree_t* tree;
page_t* page;
+ ulint offs;
ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
@@ -87,7 +88,8 @@ btr_pcur_store_position(
page_cursor = btr_pcur_get_page_cur(cursor);
rec = page_cur_get_rec(page_cursor);
- page = buf_frame_align(rec);
+ page = ut_align_down(rec, UNIV_PAGE_SIZE);
+ offs = ut_align_offset(rec, UNIV_PAGE_SIZE);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_S_FIX)
@@ -95,35 +97,33 @@ btr_pcur_store_position(
MTR_MEMO_PAGE_X_FIX));
ut_a(cursor->latch_mode != BTR_NO_LATCHES);
- if (page_get_n_recs(page) == 0) {
+ if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) {
/* It must be an empty index tree; NOTE that in this case
we do not store the modify_clock, but always do a search
if we restore the cursor position */
- ut_a(btr_page_get_next(page, mtr) == FIL_NULL
- && btr_page_get_prev(page, mtr) == FIL_NULL);
+ ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
+ ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
- if (rec == page_get_supremum_rec(page)) {
+ cursor->old_stored = BTR_PCUR_OLD_STORED;
- cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
- cursor->old_stored = BTR_PCUR_OLD_STORED;
+ if (page_rec_is_supremum_low(offs)) {
- return;
+ cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
+ } else {
+ cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
}
- cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
- cursor->old_stored = BTR_PCUR_OLD_STORED;
-
return;
}
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum_low(offs)) {
rec = page_rec_get_prev(rec);
cursor->rel_pos = BTR_PCUR_AFTER;
- } else if (rec == page_get_infimum_rec(page)) {
+ } else if (page_rec_is_infimum_low(offs)) {
rec = page_rec_get_next(rec);
@@ -139,7 +139,8 @@ btr_pcur_store_position(
&cursor->buf_size);
cursor->block_when_stored = buf_block_align(page);
- cursor->modify_clock = buf_frame_get_modify_clock(page);
+ cursor->modify_clock = buf_block_get_modify_clock(
+ cursor->block_when_stored);
}
/******************************************************************
@@ -202,33 +203,27 @@ btr_pcur_restore_position(
dtuple_t* tuple;
ulint mode;
ulint old_mode;
- ibool from_left;
mem_heap_t* heap;
- ut_a(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
- || cursor->pos_state == BTR_PCUR_IS_POSITIONED);
- if (cursor->old_stored != BTR_PCUR_OLD_STORED) {
+ if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED)
+ || UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED
+ && cursor->pos_state != BTR_PCUR_IS_POSITIONED)) {
ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t));
if (cursor->trx_if_known) {
trx_print(stderr, cursor->trx_if_known);
}
- ut_a(0);
+ ut_error;
}
- if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
- || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
+ if (UNIV_UNLIKELY(cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
+ || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
/* In these cases we do not try an optimistic restoration,
but always do a search */
- if (cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
- from_left = TRUE;
- } else {
- from_left = FALSE;
- }
-
- btr_cur_open_at_index_side(from_left,
+ btr_cur_open_at_index_side(
+ cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
btr_pcur_get_btr_cur(cursor)->index, latch_mode,
btr_pcur_get_btr_cur(cursor), mtr);
@@ -243,12 +238,13 @@ btr_pcur_restore_position(
page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
- if (latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF) {
+ if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF)
+ || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) {
/* Try optimistic restoration */
- if (buf_page_optimistic_get(latch_mode,
+ if (UNIV_LIKELY(buf_page_optimistic_get(latch_mode,
cursor->block_when_stored, page,
- cursor->modify_clock, mtr)) {
+ cursor->modify_clock, mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
@@ -297,7 +293,7 @@ btr_pcur_restore_position(
/* Save the old search mode of the cursor */
old_mode = cursor->search_mode;
- if (cursor->rel_pos == BTR_PCUR_ON) {
+ if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
mode = PAGE_CUR_LE;
} else if (cursor->rel_pos == BTR_PCUR_AFTER) {
mode = PAGE_CUR_G;
@@ -323,12 +319,10 @@ btr_pcur_restore_position(
the cursor can now be on a different page! But we can retain
the value of old_rec */
- cursor->modify_clock =
- buf_frame_get_modify_clock(btr_pcur_get_page(cursor));
-
cursor->block_when_stored =
buf_block_align(btr_pcur_get_page(cursor));
-
+ cursor->modify_clock =
+ buf_block_get_modify_clock(cursor->block_when_stored);
cursor->old_stored = BTR_PCUR_OLD_STORED;
mem_heap_free(heap);
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c
index 97fdce2df75..f705fee4275 100644
--- a/innobase/btr/btr0sea.c
+++ b/innobase/btr/btr0sea.c
@@ -435,7 +435,7 @@ btr_search_update_hash_ref(
offsets_, ULINT_UNDEFINED, &heap),
block->curr_n_fields,
block->curr_n_bytes, tree_id);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
#ifdef UNIV_SYNC_DEBUG
@@ -544,10 +544,7 @@ btr_search_check_guess(
or PAGE_CUR_GE */
mtr_t* mtr) /* in: mtr */
{
- page_t* page;
rec_t* rec;
- rec_t* prev_rec;
- rec_t* next_rec;
ulint n_unique;
ulint match;
ulint bytes;
@@ -561,7 +558,6 @@ btr_search_check_guess(
n_unique = dict_index_get_n_unique_in_tree(cursor->index);
rec = btr_cur_get_rec(cursor);
- page = buf_frame_align(rec);
ut_ad(page_rec_is_user_rec(rec));
@@ -611,13 +607,16 @@ btr_search_check_guess(
bytes = 0;
if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)) {
+ rec_t* prev_rec;
- ut_ad(rec != page_get_infimum_rec(page));
+ ut_ad(!page_rec_is_infimum(rec));
prev_rec = page_rec_get_prev(rec);
- if (prev_rec == page_get_infimum_rec(page)) {
- success = btr_page_get_prev(page, mtr) == FIL_NULL;
+ if (page_rec_is_infimum(prev_rec)) {
+ success = btr_page_get_prev(
+ buf_frame_align(prev_rec), mtr) == FIL_NULL;
+
goto exit_func;
}
@@ -632,34 +631,37 @@ btr_search_check_guess(
}
goto exit_func;
- }
-
- ut_ad(rec != page_get_supremum_rec(page));
+ } else {
+ rec_t* next_rec;
+
+ ut_ad(!page_rec_is_supremum(rec));
- next_rec = page_rec_get_next(rec);
+ next_rec = page_rec_get_next(rec);
- if (next_rec == page_get_supremum_rec(page)) {
- if (btr_page_get_next(page, mtr) == FIL_NULL) {
+ if (page_rec_is_supremum(next_rec)) {
+ if (btr_page_get_next(
+ buf_frame_align(next_rec), mtr) == FIL_NULL) {
- cursor->up_match = 0;
- success = TRUE;
- }
+ cursor->up_match = 0;
+ success = TRUE;
+ }
- goto exit_func;
- }
+ goto exit_func;
+ }
- offsets = rec_get_offsets(next_rec, cursor->index, offsets,
+ offsets = rec_get_offsets(next_rec, cursor->index, offsets,
n_unique, &heap);
- cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec,
- offsets, &match, &bytes);
- if (mode == PAGE_CUR_LE) {
- success = cmp == -1;
- cursor->up_match = match;
- } else {
- success = cmp != 1;
+ cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec,
+ offsets, &match, &bytes);
+ if (mode == PAGE_CUR_LE) {
+ success = cmp == -1;
+ cursor->up_match = match;
+ } else {
+ success = cmp != 1;
+ }
}
exit_func:
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(success);
@@ -694,7 +696,6 @@ btr_search_guess_on_hash(
buf_block_t* block;
rec_t* rec;
page_t* page;
- ibool success;
ulint fold;
ulint tuple_n_fields;
dulint tree_id;
@@ -710,7 +711,7 @@ btr_search_guess_on_hash(
/* Note that, for efficiency, the struct info may not be protected by
any latch here! */
- if (info->n_hash_potential == 0) {
+ if (UNIV_UNLIKELY(info->n_hash_potential == 0)) {
return(FALSE);
}
@@ -720,12 +721,13 @@ btr_search_guess_on_hash(
tuple_n_fields = dtuple_get_n_fields(tuple);
- if (tuple_n_fields < cursor->n_fields) {
+ if (UNIV_UNLIKELY(tuple_n_fields < cursor->n_fields)) {
return(FALSE);
}
- if ((cursor->n_bytes > 0) && (tuple_n_fields <= cursor->n_fields)) {
+ if (UNIV_UNLIKELY(tuple_n_fields == cursor->n_fields)
+ && (cursor->n_bytes > 0)) {
return(FALSE);
}
@@ -740,39 +742,31 @@ btr_search_guess_on_hash(
cursor->fold = fold;
cursor->flag = BTR_CUR_HASH;
- if (!has_search_latch) {
+ if (UNIV_LIKELY(!has_search_latch)) {
rw_lock_s_lock(&btr_search_latch);
}
- ut_a(btr_search_latch.writer != RW_LOCK_EX);
- ut_a(btr_search_latch.reader_count > 0);
+ ut_ad(btr_search_latch.writer != RW_LOCK_EX);
+ ut_ad(btr_search_latch.reader_count > 0);
rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
- if (!rec) {
- if (!has_search_latch) {
- rw_lock_s_unlock(&btr_search_latch);
- }
-
- goto failure;
+ if (UNIV_UNLIKELY(!rec)) {
+ goto failure_unlock;
}
page = buf_frame_align(rec);
- if (!has_search_latch) {
+ if (UNIV_LIKELY(!has_search_latch)) {
- success = buf_page_get_known_nowait(latch_mode, page,
+ if (UNIV_UNLIKELY(!buf_page_get_known_nowait(latch_mode, page,
BUF_MAKE_YOUNG,
__FILE__, __LINE__,
- mtr);
-
- rw_lock_s_unlock(&btr_search_latch);
-
- if (!success) {
-
- goto failure;
+ mtr))) {
+ goto failure_unlock;
}
+ rw_lock_s_unlock(&btr_search_latch);
can_only_compare_to_cursor_rec = FALSE;
#ifdef UNIV_SYNC_DEBUG
@@ -782,8 +776,8 @@ btr_search_guess_on_hash(
block = buf_block_align(page);
- if (block->state == BUF_BLOCK_REMOVE_HASH) {
- if (!has_search_latch) {
+ if (UNIV_UNLIKELY(block->state == BUF_BLOCK_REMOVE_HASH)) {
+ if (UNIV_LIKELY(!has_search_latch)) {
btr_leaf_page_release(page, latch_mode, mtr);
}
@@ -791,51 +785,33 @@ btr_search_guess_on_hash(
goto failure;
}
- ut_a(block->state == BUF_BLOCK_FILE_PAGE);
- ut_a(page_rec_is_user_rec(rec));
+ ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
+ ut_ad(page_rec_is_user_rec(rec));
btr_cur_position(index, rec, cursor);
/* Check the validity of the guess within the page */
- if (0 != ut_dulint_cmp(tree_id, btr_page_get_index_id(page))) {
-
- success = FALSE;
-/*
- fprintf(stderr, "Tree id %lu, page index id %lu fold %lu\n",
- ut_dulint_get_low(tree_id),
- ut_dulint_get_low(btr_page_get_index_id(page)),
- fold);
-*/
- } else {
- /* If we only have the latch on btr_search_latch, not on the
- page, it only protects the columns of the record the cursor
- is positioned on. We cannot look at the next of the previous
- record to determine if our guess for the cursor position is
- right. */
-
- success = btr_search_check_guess(cursor,
- can_only_compare_to_cursor_rec,
- tuple, mode, mtr);
- }
-
- if (!success) {
- if (!has_search_latch) {
+ /* If we only have the latch on btr_search_latch, not on the
+ page, it only protects the columns of the record the cursor
+ is positioned on. We cannot look at the next of the previous
+ record to determine if our guess for the cursor position is
+ right. */
+ if (UNIV_EXPECT(ut_dulint_cmp(tree_id, btr_page_get_index_id(page)), 0)
+ || !btr_search_check_guess(cursor, can_only_compare_to_cursor_rec,
+ tuple, mode, mtr)) {
+ if (UNIV_LIKELY(!has_search_latch)) {
btr_leaf_page_release(page, latch_mode, mtr);
}
goto failure;
}
- if (info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5) {
+ if (UNIV_LIKELY(info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5)) {
info->n_hash_potential++;
}
- if (info->last_hash_succ != TRUE) {
- info->last_hash_succ = TRUE;
- }
-
#ifdef notdefined
/* These lines of code can be used in a debug version to check
the correctness of the searched cursor position: */
@@ -843,15 +819,14 @@ btr_search_guess_on_hash(
info->last_hash_succ = FALSE;
/* Currently, does not work if the following fails: */
- ut_a(!has_search_latch);
+ ut_ad(!has_search_latch);
btr_leaf_page_release(page, latch_mode, mtr);
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
&cursor2, 0, mtr);
if (mode == PAGE_CUR_GE
- && btr_cur_get_rec(&cursor2) == page_get_supremum_rec(
- buf_frame_align(btr_cur_get_rec(&cursor2)))) {
+ && page_rec_is_supremum(btr_cur_get_rec(&cursor2))) {
/* If mode is PAGE_CUR_GE, then the binary search
in the index tree may actually take us to the supremum
@@ -861,22 +836,22 @@ btr_search_guess_on_hash(
btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode,
&pcur, mtr);
- ut_a(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor));
+ ut_ad(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor));
} else {
- ut_a(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor));
+ ut_ad(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor));
}
/* NOTE that it is theoretically possible that the above assertions
fail if the page of the cursor gets removed from the buffer pool
meanwhile! Thus it might not be a bug. */
-
- info->last_hash_succ = TRUE;
#endif
+ info->last_hash_succ = TRUE;
#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_succ++;
#endif
- if (!has_search_latch && buf_block_peek_if_too_old(block)) {
+ if (UNIV_LIKELY(!has_search_latch)
+ && buf_block_peek_if_too_old(block)) {
buf_page_make_young(page);
}
@@ -889,6 +864,10 @@ btr_search_guess_on_hash(
return(TRUE);
/*-------------------------------------------*/
+failure_unlock:
+ if (UNIV_LIKELY(!has_search_latch)) {
+ rw_lock_s_unlock(&btr_search_latch);
+ }
failure:
info->n_hash_fail++;
@@ -917,7 +896,6 @@ btr_search_drop_page_hash_index(
ulint n_fields;
ulint n_bytes;
rec_t* rec;
- rec_t* sup;
ulint fold;
ulint prev_fold;
dulint tree_id;
@@ -968,12 +946,10 @@ btr_search_drop_page_hash_index(
n_cached = 0;
- sup = page_get_supremum_rec(page);
-
rec = page_get_infimum_rec(page);
rec = page_rec_get_next(rec);
- if (rec != sup) {
+ if (!page_rec_is_supremum(rec)) {
ut_a(n_fields <= rec_get_n_fields(rec, block->index));
if (n_bytes > 0) {
@@ -988,7 +964,7 @@ btr_search_drop_page_hash_index(
heap = NULL;
offsets = NULL;
- while (rec != sup) {
+ while (!page_rec_is_supremum(rec)) {
/* FIXME: in a mixed tree, not all records may have enough
ordering fields: */
offsets = rec_get_offsets(rec, block->index,
@@ -1010,7 +986,7 @@ next_rec:
prev_fold = fold;
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -1090,7 +1066,6 @@ btr_search_build_page_hash_index(
buf_block_t* block;
rec_t* rec;
rec_t* next_rec;
- rec_t* sup;
ulint fold;
ulint next_fold;
dulint tree_id;
@@ -1158,15 +1133,13 @@ btr_search_build_page_hash_index(
tree_id = btr_page_get_index_id(page);
- sup = page_get_supremum_rec(page);
-
rec = page_get_infimum_rec(page);
rec = page_rec_get_next(rec);
offsets = rec_get_offsets(rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
- if (rec != sup) {
+ if (!page_rec_is_supremum(rec)) {
ut_a(n_fields <= rec_offs_n_fields(offsets));
if (n_bytes > 0) {
@@ -1188,7 +1161,7 @@ btr_search_build_page_hash_index(
for (;;) {
next_rec = page_rec_get_next(rec);
- if (next_rec == sup) {
+ if (page_rec_is_supremum(next_rec)) {
if (side == BTR_SEARCH_RIGHT_SIDE) {
@@ -1252,7 +1225,7 @@ exit_func:
mem_free(folds);
mem_free(recs);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -1370,7 +1343,7 @@ btr_search_update_hash_on_delete(
fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
ULINT_UNDEFINED, &heap), block->curr_n_fields,
block->curr_n_bytes, tree_id);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
rw_lock_x_lock(&btr_search_latch);
@@ -1443,7 +1416,6 @@ btr_search_update_hash_on_insert(
{
hash_table_t* table;
buf_block_t* block;
- page_t* page;
rec_t* rec;
rec_t* ins_rec;
rec_t* next_rec;
@@ -1488,19 +1460,18 @@ btr_search_update_hash_on_insert(
ins_rec = page_rec_get_next(rec);
next_rec = page_rec_get_next(ins_rec);
- page = buf_frame_align(rec);
offsets = rec_get_offsets(ins_rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, tree_id);
- if (next_rec != page_get_supremum_rec(page)) {
+ if (!page_rec_is_supremum(next_rec)) {
offsets = rec_get_offsets(next_rec, cursor->index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
n_bytes, tree_id);
}
- if (rec != page_get_infimum_rec(page)) {
+ if (!page_rec_is_infimum(rec)) {
offsets = rec_get_offsets(rec, cursor->index, offsets,
n_fields + (n_bytes > 0), &heap);
fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
@@ -1534,7 +1505,7 @@ btr_search_update_hash_on_insert(
}
check_next_rec:
- if (next_rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(next_rec)) {
if (side == BTR_SEARCH_RIGHT_SIDE) {
@@ -1573,7 +1544,7 @@ check_next_rec:
}
function_exit:
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
if (locked) {
@@ -1662,7 +1633,7 @@ btr_search_validate(void)
}
rw_lock_x_unlock(&btr_search_latch);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 89f851709db..fe4498e6f10 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -223,13 +223,14 @@ in the free list to the frames.
buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */
+#ifdef UNIV_DEBUG
ulint buf_dbg_counter = 0; /* This is used to insert validation
operations in excution in the
debug version */
ibool buf_debug_prints = FALSE; /* If this is set TRUE,
the program prints info whenever
read-ahead or flush occurs */
-
+#endif /* UNIV_DEBUG */
/************************************************************************
Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value on
@@ -1286,8 +1287,9 @@ buf_page_optimistic_get_func(
/* If AWE is used, block may have a different frame now, e.g., NULL */
- if (block->state != BUF_BLOCK_FILE_PAGE || block->frame != guess) {
-
+ if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE)
+ || UNIV_UNLIKELY(block->frame != guess)) {
+ exit_func:
mutex_exit(&(buf_pool->mutex));
return(FALSE);
@@ -1320,19 +1322,17 @@ buf_page_optimistic_get_func(
fix_type = MTR_MEMO_PAGE_X_FIX;
}
- if (!success) {
+ if (UNIV_UNLIKELY(!success)) {
mutex_enter(&(buf_pool->mutex));
block->buf_fix_count--;
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
-#endif
- mutex_exit(&(buf_pool->mutex));
-
- return(FALSE);
+#endif
+ goto exit_func;
}
- if (!UT_DULINT_EQ(modify_clock, block->modify_clock)) {
+ if (UNIV_UNLIKELY(!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 */
@@ -1347,10 +1347,8 @@ buf_page_optimistic_get_func(
block->buf_fix_count--;
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
-#endif
- mutex_exit(&(buf_pool->mutex));
-
- return(FALSE);
+#endif
+ goto exit_func;
}
mtr_memo_push(mtr, block, fix_type);
@@ -1368,7 +1366,7 @@ buf_page_optimistic_get_func(
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(block->file_page_was_freed == FALSE);
#endif
- if (!accessed) {
+ if (UNIV_UNLIKELY(!accessed)) {
/* In the case of a first access, try to apply linear
read-ahead */
@@ -1742,10 +1740,12 @@ buf_page_create(
/* If we get here, the page was not in buf_pool: init it there */
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr, "Creating space %lu page %lu to buffer\n",
(ulong) space, (ulong) offset);
}
+#endif /* UNIV_DEBUG */
block = free_block;
@@ -1896,9 +1896,11 @@ buf_page_io_complete(
rw_lock_x_unlock_gen(&(block->lock), BUF_IO_READ);
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fputs("Has read ", stderr);
}
+#endif /* UNIV_DEBUG */
} else {
ut_ad(io_type == BUF_IO_WRITE);
@@ -1911,17 +1913,21 @@ buf_page_io_complete(
buf_pool->n_pages_written++;
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fputs("Has written ", stderr);
}
+#endif /* UNIV_DEBUG */
}
mutex_exit(&(buf_pool->mutex));
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr, "page space %lu page no %lu\n",
(ulong) block->space, (ulong) block->offset);
}
+#endif /* UNIV_DEBUG */
}
/*************************************************************************
@@ -1950,6 +1956,7 @@ buf_pool_invalidate(void)
mutex_exit(&(buf_pool->mutex));
}
+#ifdef UNIV_DEBUG
/*************************************************************************
Validates the buffer buf_pool data structure. */
@@ -2094,10 +2101,6 @@ buf_print(void)
n_found = 0;
- for (i = 0 ; i < size; i++) {
- counts[i] = 0;
- }
-
for (i = 0; i < size; i++) {
frame = buf_pool_get_nth_block(buf_pool, i)->frame;
@@ -2149,6 +2152,7 @@ buf_print(void)
ut_a(buf_validate());
}
+#endif /* UNIV_DEBUG */
/*************************************************************************
Returns the number of latched pages in the buffer pool. */
diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
index 592ed972376..ffb16790b2d 100644
--- a/innobase/buf/buf0flu.c
+++ b/innobase/buf/buf0flu.c
@@ -586,11 +586,13 @@ buf_flush_try_page(
rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
}
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Flushing page space %lu, page no %lu \n",
(ulong) block->space, (ulong) block->offset);
}
+#endif /* UNIV_DEBUG */
buf_flush_write_block_low(block);
@@ -674,12 +676,14 @@ buf_flush_try_page(
rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Flushing single page space %lu, page no %lu \n",
(ulong) block->space,
(ulong) block->offset);
}
+#endif /* UNIV_DEBUG */
buf_flush_write_block_low(block);
@@ -906,6 +910,7 @@ buf_flush_batch(
buf_flush_buffered_writes();
+#ifdef UNIV_DEBUG
if (buf_debug_prints && page_count > 0) {
ut_a(flush_type == BUF_FLUSH_LRU
|| flush_type == BUF_FLUSH_LIST);
@@ -914,6 +919,7 @@ buf_flush_batch(
: "Flushed %lu pages in flush list flush\n",
(ulong) page_count);
}
+#endif /* UNIV_DEBUG */
if (page_count != ULINT_UNDEFINED)
srv_buf_pool_flushed+= page_count;
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index 18c4f8c10fb..a0157da2d42 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -213,12 +213,14 @@ buf_LRU_search_and_free_block(
ut_a(block->in_LRU_list);
if (buf_flush_ready_for_replace(block)) {
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Putting space %lu page %lu to free list\n",
(ulong) block->space,
(ulong) block->offset);
}
+#endif /* UNIV_DEBUG */
buf_LRU_block_remove_hashed_page(block);
@@ -919,7 +921,8 @@ buf_LRU_block_free_hashed_page(
buf_LRU_block_free_non_file_page(block);
}
-
+
+#ifdef UNIV_DEBUG
/**************************************************************************
Validates the LRU list. */
@@ -1050,3 +1053,4 @@ buf_LRU_print(void)
mutex_exit(&(buf_pool->mutex));
}
+#endif /* UNIV_DEBUG */
diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c
index d9dc2ca93f5..813ca589907 100644
--- a/innobase/buf/buf0rea.c
+++ b/innobase/buf/buf0rea.c
@@ -288,12 +288,14 @@ buf_read_ahead_random(
os_aio_simulated_wake_handler_threads();
+#ifdef UNIV_DEBUG
if (buf_debug_prints && (count > 0)) {
fprintf(stderr,
"Random read-ahead space %lu offset %lu pages %lu\n",
(ulong) space, (ulong) offset,
(ulong) count);
}
+#endif /* UNIV_DEBUG */
++srv_read_ahead_rnd;
return(count);
@@ -575,11 +577,13 @@ buf_read_ahead_linear(
/* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin();
+#ifdef UNIV_DEBUG
if (buf_debug_prints && (count > 0)) {
fprintf(stderr,
"LINEAR read-ahead space %lu offset %lu pages %lu\n",
(ulong) space, (ulong) offset, (ulong) count);
}
+#endif /* UNIV_DEBUG */
++srv_read_ahead_seq;
return(count);
@@ -641,11 +645,13 @@ buf_read_ibuf_merge_pages(
/* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin();
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Ibuf merge read-ahead space %lu pages %lu\n",
(ulong) space_ids[0], (ulong) n_stored);
}
+#endif /* UNIV_DEBUG */
}
/************************************************************************
@@ -711,8 +717,10 @@ buf_read_recv_pages(
/* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin();
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Recovery applies read-ahead pages %lu\n", (ulong) n_stored);
}
+#endif /* UNIV_DEBUG */
}
diff --git a/innobase/configure.in b/innobase/configure.in
index baf11272ab9..c56bd8274c4 100644
--- a/innobase/configure.in
+++ b/innobase/configure.in
@@ -117,6 +117,13 @@ case "$target" in
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
esac
+# must go in pair with AR as set by MYSQL_CHECK_AR
+if test -z "$ARFLAGS"
+then
+ ARFLAGS="cru"
+fi
+AC_SUBST(ARFLAGS)
+
AC_OUTPUT(Makefile os/Makefile ut/Makefile btr/Makefile dnl
buf/Makefile data/Makefile dnl
dict/Makefile dyn/Makefile dnl
diff --git a/innobase/data/data0data.c b/innobase/data/data0data.c
index 5f74dde8710..194213a04e1 100644
--- a/innobase/data/data0data.c
+++ b/innobase/data/data0data.c
@@ -502,7 +502,7 @@ dtuple_convert_big_rec(
size = rec_get_converted_size(index, entry);
- if (size > 1000000000) {
+ if (UNIV_UNLIKELY(size > 1000000000)) {
fprintf(stderr,
"InnoDB: Warning: tuple size very big: %lu\n", (ulong) size);
fputs("InnoDB: Tuple contents: ", stderr);
diff --git a/innobase/data/data0type.c b/innobase/data/data0type.c
index 3fcd666b5a5..d4264ad2926 100644
--- a/innobase/data/data0type.c
+++ b/innobase/data/data0type.c
@@ -39,7 +39,6 @@ column definitions, or records in the insert buffer, we use this
charset-collation code for them. */
ulint data_mysql_default_charset_coll = 99999999;
-ulint data_mysql_latin1_swedish_charset_coll = 99999999;
dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0, 0, 0};
dtype_t* dtype_binary = &dtype_binary_val;
@@ -64,9 +63,10 @@ dtype_get_at_most_n_mbchars(
{
#ifndef UNIV_HOTBACKUP
ut_a(data_len != UNIV_SQL_NULL);
- ut_a(!(prefix_len % dtype->mbmaxlen));
+ ut_ad(!dtype->mbmaxlen || !(prefix_len % dtype->mbmaxlen));
if (dtype->mbminlen != dtype->mbmaxlen) {
+ ut_a(!(prefix_len % dtype->mbmaxlen));
return(innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(dtype->prtype),
prefix_len, data_len, str));
diff --git a/innobase/dict/dict0boot.c b/innobase/dict/dict0boot.c
index 0f6d55c9341..18a707a1b93 100644
--- a/innobase/dict/dict0boot.c
+++ b/innobase/dict/dict0boot.c
@@ -66,15 +66,6 @@ dict_hdr_get_new_id(
dict_hdr = dict_hdr_get(&mtr);
id = mtr_read_dulint(dict_hdr + type, &mtr);
-
- /* Add some dummy code here because otherwise pgcc seems to
- compile wrong */
-
- if (0 == ut_dulint_cmp(id, ut_dulint_max)) {
- /* TO DO: remove this code, or make it conditional */
- ut_dbg_null_ptr = 0;
- }
-
id = ut_dulint_add(id, 1);
mlog_write_dulint(dict_hdr + type, id, &mtr);
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index 1f12386e413..c7d6ffd2c22 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -736,7 +736,7 @@ dict_truncate_index_tree(
dulint index_id;
byte* ptr;
ulint len;
- ibool comp;
+ ulint comp;
dict_index_t* index;
#ifdef UNIV_SYNC_DEBUG
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 0c39defeada..9580a80e7e7 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -1453,7 +1453,7 @@ dict_index_add_to_cache(
/* Increment the ord_part counts in columns which are ordering */
- if (index->type & DICT_UNIVERSAL) {
+ if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
n_ord = new_index->n_fields;
} else {
n_ord = dict_index_get_n_unique(new_index);
@@ -1482,7 +1482,7 @@ dict_index_add_to_cache(
new_index->tree = tree;
}
- if (!(new_index->type & DICT_UNIVERSAL)) {
+ if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
new_index->stat_n_diff_key_vals =
mem_heap_alloc(new_index->heap,
@@ -1683,7 +1683,7 @@ dict_index_copy_types(
dtype_t* type;
ulint i;
- if (index->type & DICT_UNIVERSAL) {
+ if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
dtuple_set_types_binary(tuple, n_fields);
return;
@@ -1779,7 +1779,7 @@ dict_index_build_internal_clust(
dict_index_copy(new_index, index, 0, index->n_fields);
}
- if (index->type & DICT_UNIVERSAL) {
+ if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
/* No fixed number of fields determines an entry uniquely */
new_index->n_uniq = ULINT_MAX;
@@ -3682,7 +3682,7 @@ dict_tree_find_index_low(
table = index->table;
if ((index->type & DICT_CLUSTERED)
- && (table->type != DICT_TABLE_ORDINARY)) {
+ && UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) {
/* Get the mix id of the record */
ut_a(!table->comp);
@@ -3838,7 +3838,7 @@ dict_tree_build_node_ptr(
ind = dict_tree_find_index_low(tree, rec);
- if (tree->type & DICT_UNIVERSAL) {
+ if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
/* In a universal index tree, we take the whole record as
the node pointer if the reord is on the leaf level,
on non-leaf levels we remove the last field, which
@@ -3903,9 +3903,10 @@ dict_tree_copy_rec_order_prefix(
dict_index_t* index;
ulint n;
+ UNIV_PREFETCH_R(rec);
index = dict_tree_find_index_low(tree, rec);
- if (tree->type & DICT_UNIVERSAL) {
+ if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
ut_a(!index->table->comp);
n = rec_get_n_fields_old(rec);
} else {
@@ -3957,7 +3958,7 @@ dict_index_calc_min_rec_len(
ulint sum = 0;
ulint i;
- if (index->table->comp) {
+ if (UNIV_LIKELY(index->table->comp)) {
ulint nullable = 0;
sum = REC_N_NEW_EXTRA_BYTES;
for (i = 0; i < dict_index_get_n_fields(index); i++) {
@@ -4277,9 +4278,11 @@ dict_index_print_low(
putc('\n', stderr);
-/* btr_print_size(tree); */
+#ifdef UNIV_BTR_PRINT
+ btr_print_size(tree);
-/* btr_print_tree(tree, 7); */
+ btr_print_tree(tree, 7);
+#endif /* UNIV_BTR_PRINT */
}
/**************************************************************************
diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c
index 48b9f28d292..eec35310039 100644
--- a/innobase/dict/dict0mem.c
+++ b/innobase/dict/dict0mem.c
@@ -42,6 +42,7 @@ dict_mem_table_create(
mem_heap_t* heap;
ut_ad(name);
+ ut_ad(comp == FALSE || comp == TRUE);
heap = mem_heap_create(DICT_HEAP_SIZE);
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index 8600f583dbd..20f522c1a60 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -99,7 +99,6 @@ ulint fil_n_pending_tablespace_flushes = 0;
fil_addr_t fil_addr_null = {FIL_NULL, 0};
/* File node of a tablespace or the log data space */
-typedef struct fil_node_struct fil_node_t;
struct fil_node_struct {
fil_space_t* space; /* backpointer to the space where this node
belongs */
@@ -3411,9 +3410,9 @@ fil_extend_space_to_desired_size(
fil_space_t* space;
byte* buf2;
byte* buf;
+ ulint buf_size;
ulint start_page_no;
ulint file_start_page_no;
- ulint n_pages;
ulint offset_high;
ulint offset_low;
ibool success = TRUE;
@@ -3438,22 +3437,20 @@ fil_extend_space_to_desired_size(
fil_node_prepare_for_io(node, system, space);
- /* Extend 1 MB at a time */
-
- buf2 = mem_alloc(1024 * 1024 + UNIV_PAGE_SIZE);
- buf = ut_align(buf2, UNIV_PAGE_SIZE);
-
- memset(buf, '\0', 1024 * 1024);
-
start_page_no = space->size;
file_start_page_no = space->size - node->size;
- while (start_page_no < size_after_extend) {
- n_pages = size_after_extend - start_page_no;
+ /* Extend at most 64 pages at a time */
+ buf_size = ut_min(64, size_after_extend - start_page_no)
+ * UNIV_PAGE_SIZE;
+ buf2 = mem_alloc(buf_size + UNIV_PAGE_SIZE);
+ buf = ut_align(buf2, UNIV_PAGE_SIZE);
- if (n_pages > (1024 * 1024) / UNIV_PAGE_SIZE) {
- n_pages = (1024 * 1024) / UNIV_PAGE_SIZE;
- }
+ memset(buf, 0, buf_size);
+
+ while (start_page_no < size_after_extend) {
+ ulint n_pages = ut_min(buf_size / UNIV_PAGE_SIZE,
+ size_after_extend - start_page_no);
offset_high = (start_page_no - file_start_page_no)
/ (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE));
@@ -4035,7 +4032,7 @@ fil_aio_wait(
if (os_aio_use_native_aio) {
srv_set_io_thread_op_info(segment, "native aio handle");
#ifdef WIN_ASYNC_IO
- ret = os_aio_windows_handle(segment, 0, (void**) &fil_node,
+ ret = os_aio_windows_handle(segment, 0, &fil_node,
&message, &type);
#elif defined(POSIX_ASYNC_IO)
ret = os_aio_posix_handle(segment, &fil_node, &message);
@@ -4046,7 +4043,7 @@ fil_aio_wait(
} else {
srv_set_io_thread_op_info(segment, "simulated aio handle");
- ret = os_aio_simulated_handle(segment, (void**) &fil_node,
+ ret = os_aio_simulated_handle(segment, &fil_node,
&message, &type);
}
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index ef8e70646c6..ad4228f6797 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -2325,7 +2325,6 @@ fseg_alloc_free_page_low(
dulint seg_id;
ulint used;
ulint reserved;
- fil_addr_t first;
xdes_t* descr; /* extent of the hinted page */
ulint ret_page; /* the allocated page offset, FIL_NULL
if could not be allocated */
@@ -2428,6 +2427,8 @@ fseg_alloc_free_page_low(
} else if (reserved - used > 0) {
/* 5. We take any unused page from the segment
==============================================*/
+ fil_addr_t first;
+
if (flst_get_len(seg_inode + FSEG_NOT_FULL, mtr) > 0) {
first = flst_get_first(seg_inode + FSEG_NOT_FULL,
mtr);
@@ -2435,6 +2436,7 @@ fseg_alloc_free_page_low(
first = flst_get_first(seg_inode + FSEG_FREE, mtr);
} else {
ut_error;
+ return(FIL_NULL);
}
ret_descr = xdes_lst_get_descriptor(space, first, mtr);
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index 5ad61e2590f..d7fa48b6e66 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -1889,7 +1889,7 @@ ibuf_get_merge_page_nos(
contract the tree, FALSE if this is called
when a single page becomes full and we look
if it pays to read also nearby pages */
- rec_t* first_rec,/* in: record from which we read up and down
+ rec_t* rec, /* in: record from which we read up and down
in the chain of records */
ulint* space_ids,/* in/out: space id's of the pages */
ib_longlong* space_versions,/* in/out: tablespace version
@@ -1907,47 +1907,42 @@ ibuf_get_merge_page_nos(
ulint first_space_id;
ulint rec_page_no;
ulint rec_space_id;
- rec_t* rec;
ulint sum_volumes;
ulint volume_for_page;
ulint rec_volume;
ulint limit;
- page_t* page;
ulint n_pages;
*n_stored = 0;
limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool->curr_size / 4);
- page = buf_frame_align(first_rec);
-
- if (first_rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
- first_rec = page_rec_get_prev(first_rec);
+ rec = page_rec_get_prev(rec);
}
- if (first_rec == page_get_infimum_rec(page)) {
+ if (page_rec_is_infimum(rec)) {
- first_rec = page_rec_get_next(first_rec);
+ rec = page_rec_get_next(rec);
}
- if (first_rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
return(0);
}
- rec = first_rec;
- first_page_no = ibuf_rec_get_page_no(first_rec);
- first_space_id = ibuf_rec_get_space(first_rec);
+ first_page_no = ibuf_rec_get_page_no(rec);
+ first_space_id = ibuf_rec_get_space(rec);
n_pages = 0;
prev_page_no = 0;
prev_space_id = 0;
- /* Go backwards from the first_rec until we reach the border of the
+ /* Go backwards from the first rec until we reach the border of the
'merge area', or the page start or the limit of storeable pages is
reached */
- while ((rec != page_get_infimum_rec(page)) && (n_pages < limit)) {
+ while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
rec_page_no = ibuf_rec_get_page_no(rec);
rec_space_id = ibuf_rec_get_space(rec);
@@ -1982,7 +1977,7 @@ ibuf_get_merge_page_nos(
volume_for_page = 0;
while (*n_stored < limit) {
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
/* When no more records available, mark this with
another 'impossible' pair of space id, page no */
rec_page_no = 1;
@@ -2311,12 +2306,12 @@ ibuf_get_volume_buffered(
page = buf_frame_align(rec);
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
rec = page_rec_get_prev(rec);
}
for (;;) {
- if (rec == page_get_infimum_rec(page)) {
+ if (page_rec_is_infimum(rec)) {
break;
}
@@ -2351,7 +2346,7 @@ ibuf_get_volume_buffered(
rec = page_rec_get_prev(rec);
for (;;) {
- if (rec == page_get_infimum_rec(prev_page)) {
+ if (page_rec_is_infimum(rec)) {
/* We cannot go to yet a previous page, because we
do not have the x-latch on it, and cannot acquire one
@@ -2374,12 +2369,12 @@ ibuf_get_volume_buffered(
count_later:
rec = btr_pcur_get_rec(pcur);
- if (rec != page_get_supremum_rec(page)) {
+ if (!page_rec_is_supremum(rec)) {
rec = page_rec_get_next(rec);
}
for (;;) {
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
break;
}
@@ -2414,7 +2409,7 @@ count_later:
rec = page_rec_get_next(rec);
for (;;) {
- if (rec == page_get_supremum_rec(next_page)) {
+ if (page_rec_is_supremum(rec)) {
/* We give up */
@@ -2815,7 +2810,7 @@ ibuf_insert_to_index_page(
ut_ad(ibuf_inside());
ut_ad(dtuple_check_typed(entry));
- if (index->table->comp != page_is_comp(page)) {
+ if (UNIV_UNLIKELY(index->table->comp != (ibool)!!page_is_comp(page))) {
fputs(
"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
"InnoDB: but the 'compact' flag does not match!\n", stderr);
@@ -2824,7 +2819,8 @@ ibuf_insert_to_index_page(
rec = page_rec_get_next(page_get_infimum_rec(page));
- if (rec_get_n_fields(rec, index) != dtuple_get_n_fields(entry)) {
+ if (UNIV_UNLIKELY(rec_get_n_fields(rec, index)
+ != dtuple_get_n_fields(entry))) {
fputs(
"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
"InnoDB: but the number of fields does not match!\n", stderr);
@@ -2848,7 +2844,7 @@ ibuf_insert_to_index_page(
if (low_match == dtuple_get_n_fields(entry)) {
rec = page_cur_get_rec(&page_cur);
- btr_cur_del_unmark_for_ibuf(rec, index, mtr);
+ btr_cur_del_unmark_for_ibuf(rec, mtr);
} else {
rec = page_cur_tuple_insert(&page_cur, entry, index, mtr);
@@ -2861,8 +2857,8 @@ ibuf_insert_to_index_page(
PAGE_CUR_LE, &page_cur);
/* This time the record must fit */
- if (!page_cur_tuple_insert(&page_cur, entry,
- index, mtr)) {
+ if (UNIV_UNLIKELY(!page_cur_tuple_insert(
+ &page_cur, entry, index, mtr))) {
ut_print_timestamp(stderr);
@@ -2969,7 +2965,9 @@ ibuf_delete_rec(
btr_pcur_commit_specify_mtr(pcur, mtr);
fputs("InnoDB: Validating insert buffer tree:\n", stderr);
- ut_a(btr_validate_tree(ibuf_data->index->tree));
+ if (!btr_validate_tree(ibuf_data->index->tree, NULL)) {
+ ut_error;
+ }
fprintf(stderr, "InnoDB: ibuf tree ok\n");
fflush(stderr);
diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h
index 0b19e64d4e0..1f3a32fa70c 100644
--- a/innobase/include/btr0btr.h
+++ b/innobase/include/btr0btr.h
@@ -168,7 +168,7 @@ btr_create(
ulint type, /* in: type of the index */
ulint space, /* in: space where created */
dulint index_id,/* in: index id */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr); /* in: mini-transaction handle */
/****************************************************************
Frees a B-tree except the root page, which MUST be freed after this
@@ -276,7 +276,7 @@ void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes on the upper level the node pointer to a page. */
@@ -336,7 +336,7 @@ btr_parse_set_min_rec_mark(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
@@ -398,6 +398,7 @@ btr_page_free_low(
page_t* page, /* in: page to be freed, x-latched */
ulint level, /* in: page level */
mtr_t* mtr); /* in: mtr */
+#ifdef UNIV_BTR_PRINT
/*****************************************************************
Prints size info of a B-tree. */
@@ -414,6 +415,7 @@ btr_print_tree(
dict_tree_t* tree, /* in: tree */
ulint width); /* in: print this many entries from start
and end */
+#endif /* UNIV_BTR_PRINT */
/****************************************************************
Checks the size and number of fields in a record based on the definition of
the index. */
@@ -434,7 +436,8 @@ ibool
btr_validate_tree(
/*==============*/
/* out: TRUE if ok */
- dict_tree_t* tree); /* in: tree */
+ dict_tree_t* tree, /* in: tree */
+ trx_t* trx); /* in: transaction or NULL */
#define BTR_N_LEAF_PAGES 1
#define BTR_TOTAL_SIZE 2
diff --git a/innobase/include/btr0btr.ic b/innobase/include/btr0btr.ic
index 1d1f97d3668..a0860b1c3a7 100644
--- a/innobase/include/btr0btr.ic
+++ b/innobase/include/btr0btr.ic
@@ -200,10 +200,10 @@ btr_node_ptr_get_child_page_no(
page_no = mach_read_from_4(field);
- if (page_no == 0) {
+ if (UNIV_UNLIKELY(page_no == 0)) {
fprintf(stderr,
"InnoDB: a nonsensical page number 0 in a node ptr record at offset %lu\n",
- (unsigned long)(rec - buf_frame_align(rec)));
+ (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE));
buf_page_print(buf_frame_align(rec));
}
diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h
index 0a8d8ceaeb7..352d1739b6a 100644
--- a/innobase/include/btr0cur.h
+++ b/innobase/include/btr0cur.h
@@ -284,7 +284,6 @@ void
btr_cur_del_unmark_for_ibuf(
/*========================*/
rec_t* rec, /* in: record to delete unmark */
- dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Tries to compress a page of the tree on the leaf level. It is assumed
@@ -389,7 +388,6 @@ btr_cur_parse_del_mark_set_sec_rec(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
- dict_index_t* index, /* in: index corresponding to page */
page_t* page); /* in: page or NULL */
/***********************************************************************
Estimates the number of rows in a given index range. */
diff --git a/innobase/include/btr0cur.ic b/innobase/include/btr0cur.ic
index dcad3e9e14d..bf8a6efb68d 100644
--- a/innobase/include/btr0cur.ic
+++ b/innobase/include/btr0cur.ic
@@ -52,7 +52,9 @@ btr_cur_get_page(
/* out: pointer to page */
btr_cur_t* cursor) /* in: tree cursor */
{
- return(buf_frame_align(page_cur_get_rec(&(cursor->page_cur))));
+ page_t* page = buf_frame_align(page_cur_get_rec(&(cursor->page_cur)));
+ ut_ad(!!page_is_comp(page) == cursor->index->table->comp);
+ return(page);
}
/*************************************************************
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index 5ee323f1b1e..ae8d0411c12 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -56,9 +56,11 @@ Created 11/5/1995 Heikki Tuuri
#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
extern buf_pool_t* buf_pool; /* The buffer pool of the database */
+#ifdef UNIV_DEBUG
extern ibool buf_debug_prints;/* If this is set TRUE, the program
prints info whenever read or flush
occurs */
+#endif /* UNIV_DEBUG */
extern ulint srv_buf_pool_write_requests; /* variable to count write request
issued */
@@ -382,10 +384,10 @@ Returns the value of the modify clock. The caller must have an s-lock
or x-lock on the block. */
UNIV_INLINE
dulint
-buf_frame_get_modify_clock(
+buf_block_get_modify_clock(
/*=======================*/
/* out: value */
- buf_frame_t* frame); /* in: pointer to a frame */
+ buf_block_t* block); /* in: block */
/************************************************************************
Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value
@@ -480,12 +482,20 @@ buf_pool_is_block(
/*==============*/
/* out: TRUE if pointer to block */
void* ptr); /* in: pointer to memory */
+#ifdef UNIV_DEBUG
/*************************************************************************
Validates the buffer pool data structure. */
ibool
buf_validate(void);
/*==============*/
+/*************************************************************************
+Prints info of the buffer pool data structure. */
+
+void
+buf_print(void);
+/*============*/
+#endif /* UNIV_DEBUG */
/************************************************************************
Prints a page to stderr. */
@@ -494,12 +504,6 @@ buf_page_print(
/*===========*/
byte* read_buf); /* in: a database page */
/*************************************************************************
-Prints info of the buffer pool data structure. */
-
-void
-buf_print(void);
-/*============*/
-/*************************************************************************
Returns the number of latched pages in the buffer pool. */
ulint
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index 681a0ef000a..d949254d47d 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -11,10 +11,11 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0rea.h"
#include "mtr0mtr.h"
+#ifdef UNIV_DEBUG
extern ulint buf_dbg_counter; /* This is used to insert validation
operations in execution in the
debug version */
-
+#endif /* UNIV_DEBUG */
/************************************************************************
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
@@ -26,12 +27,8 @@ buf_block_peek_if_too_old(
/* out: TRUE if should be made younger */
buf_block_t* block) /* in: block to make younger */
{
- if (buf_pool->freed_page_clock >= block->freed_page_clock
- + 1 + (buf_pool->curr_size / 1024)) {
- return(TRUE);
- }
-
- return(FALSE);
+ return(buf_pool->freed_page_clock >= block->freed_page_clock
+ + 1 + (buf_pool->curr_size / 1024));
}
/*************************************************************************
@@ -210,8 +207,8 @@ buf_block_align(
frame_zero = buf_pool->frame_zero;
- if ((ulint)ptr < (ulint)frame_zero
- || (ulint)ptr > (ulint)(buf_pool->high_end)) {
+ if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero)
+ || UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -246,8 +243,8 @@ buf_frame_align(
frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
- if (((ulint)frame < (ulint)(buf_pool->frame_zero))
- || (ulint)frame >= (ulint)(buf_pool->high_end)) {
+ if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero))
+ || UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -485,17 +482,11 @@ Returns the value of the modify clock. The caller must have an s-lock
or x-lock on the block. */
UNIV_INLINE
dulint
-buf_frame_get_modify_clock(
+buf_block_get_modify_clock(
/*=======================*/
/* out: value */
- buf_frame_t* frame) /* in: pointer to a frame */
+ buf_block_t* block) /* in: block */
{
- buf_block_t* block;
-
- ut_ad(frame);
-
- 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));
diff --git a/innobase/include/buf0lru.h b/innobase/include/buf0lru.h
index 45164dd561e..fb29b44ba98 100644
--- a/innobase/include/buf0lru.h
+++ b/innobase/include/buf0lru.h
@@ -122,6 +122,7 @@ void
buf_LRU_make_block_old(
/*===================*/
buf_block_t* block); /* in: control block */
+#ifdef UNIV_DEBUG
/**************************************************************************
Validates the LRU list. */
@@ -134,6 +135,7 @@ Prints the LRU list. */
void
buf_LRU_print(void);
/*===============*/
+#endif /* UNIV_DEBUG */
#ifndef UNIV_NONINL
#include "buf0lru.ic"
diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h
index a4d2c1a2e1d..7e9692eca5a 100644
--- a/innobase/include/data0type.h
+++ b/innobase/include/data0type.h
@@ -12,7 +12,7 @@ Created 1/16/1996 Heikki Tuuri
#include "univ.i"
extern ulint data_mysql_default_charset_coll;
-extern ulint data_mysql_latin1_swedish_charset_coll;
+#define DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL 8
/* SQL data type struct */
typedef struct dtype_struct dtype_t;
diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic
index a87a08ca582..06d45dd5501 100644
--- a/innobase/include/data0type.ic
+++ b/innobase/include/data0type.ic
@@ -388,8 +388,8 @@ dtype_get_fixed_size(
dtype_get_charset_coll(type->prtype),
&mbminlen, &mbmaxlen);
- if (type->mbminlen != mbminlen
- || type->mbmaxlen != mbmaxlen) {
+ if (UNIV_UNLIKELY(type->mbminlen != mbminlen)
+ || UNIV_UNLIKELY(type->mbmaxlen != mbmaxlen)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: "
diff --git a/innobase/include/dyn0dyn.h b/innobase/include/dyn0dyn.h
index abee62300e3..1df976a5301 100644
--- a/innobase/include/dyn0dyn.h
+++ b/innobase/include/dyn0dyn.h
@@ -132,7 +132,7 @@ void
dyn_push_string(
/*============*/
dyn_array_t* arr, /* in: dyn array */
- byte* str, /* in: string to write */
+ const byte* str, /* in: string to write */
ulint len); /* in: string length */
/*#################################################################*/
diff --git a/innobase/include/dyn0dyn.ic b/innobase/include/dyn0dyn.ic
index b6c4808398b..c1b8f2cb8ce 100644
--- a/innobase/include/dyn0dyn.ic
+++ b/innobase/include/dyn0dyn.ic
@@ -324,10 +324,9 @@ void
dyn_push_string(
/*============*/
dyn_array_t* arr, /* in: dyn array */
- byte* str, /* in: string to write */
+ const byte* str, /* in: string to write */
ulint len) /* in: string length */
{
- byte* ptr;
ulint n_copied;
while (len > 0) {
@@ -337,9 +336,7 @@ dyn_push_string(
n_copied = len;
}
- ptr = (byte*) dyn_array_push(arr, n_copied);
-
- ut_memcpy(ptr, str, n_copied);
+ memcpy(dyn_array_push(arr, n_copied), str, n_copied);
str += n_copied;
len -= n_copied;
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index 45a81a4ac77..20b1f1d7145 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -19,7 +19,9 @@ Created 5/7/1996 Heikki Tuuri
#include "read0types.h"
#include "hash0hash.h"
+#ifdef UNIV_DEBUG
extern ibool lock_print_waits;
+#endif /* UNIV_DEBUG */
/* Buffer for storing information about the most recent deadlock error */
extern FILE* lock_latest_err_file;
@@ -216,6 +218,7 @@ actual record is being moved. */
void
lock_rec_store_on_page_infimum(
/*===========================*/
+ page_t* page, /* in: page containing the record */
rec_t* rec); /* in: record whose lock state is stored
on the infimum record of the same page; lock
bits are reset on the record */
@@ -412,9 +415,7 @@ lock_table(
/* out: DB_SUCCESS, DB_LOCK_WAIT,
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
- does nothing;
- if LOCK_TABLE_EXP bits are set,
- creates an explicit table lock */
+ does nothing */
dict_table_t* table, /* in: database table in dictionary cache */
ulint mode, /* in: lock mode */
que_thr_t* thr); /* in: query thread */
@@ -451,15 +452,6 @@ lock_release_off_kernel(
/*====================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
-Releases table locks explicitly requested with LOCK TABLES (indicated by
-lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
-because of these locks. */
-
-void
-lock_release_tables_off_kernel(
-/*===========================*/
- trx_t* trx); /* in: transaction */
-/*************************************************************************
Cancels a waiting lock request and releases possible other transactions
waiting behind it. */
@@ -618,9 +610,6 @@ extern lock_sys_t* lock_sys;
/* Lock types */
#define LOCK_TABLE 16 /* these type values should be so high that */
#define LOCK_REC 32 /* they can be ORed to the lock mode */
-#define LOCK_TABLE_EXP 80 /* explicit table lock (80 = 16 + 64) */
-#define LOCK_TABLE_TRANSACTIONAL 144
- /* transactional table lock (144 = 16 + 128)*/
#define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the
type_mode field in a lock */
/* Waiting lock flag */
diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h
index d14a116072d..7f3f10438b4 100644
--- a/innobase/include/log0log.h
+++ b/innobase/include/log0log.h
@@ -17,8 +17,12 @@ Created 12/9/1995 Heikki Tuuri
typedef struct log_struct log_t;
typedef struct log_group_struct log_group_t;
+#ifdef UNIV_DEBUG
extern ibool log_do_write;
extern ibool log_debug_writes;
+#else /* UNIV_DEBUG */
+# define log_do_write TRUE
+#endif /* UNIV_DEBUG */
/* Wait modes for log_write_up_to */
#define LOG_NO_WAIT 91
diff --git a/innobase/include/mach0data.h b/innobase/include/mach0data.h
index 7ad760cd60f..f9a3ff521d5 100644
--- a/innobase/include/mach0data.h
+++ b/innobase/include/mach0data.h
@@ -52,6 +52,27 @@ mach_read_from_2(
/*=============*/
/* out: ulint integer, >= 0, < 64k */
byte* b); /* in: pointer to two bytes */
+
+/************************************************************
+The following function is used to convert a 16-bit data item
+to the canonical format, for fast bytewise equality test
+against memory. */
+UNIV_INLINE
+uint16
+mach_encode_2(
+/*==========*/
+ /* out: 16-bit integer in canonical format */
+ ulint n); /* in: integer in machine-dependent format */
+/************************************************************
+The following function is used to convert a 16-bit data item
+from the canonical format, for fast bytewise equality test
+against memory. */
+UNIV_INLINE
+ulint
+mach_decode_2(
+/*==========*/
+ /* out: integer in machine-dependent format */
+ uint16 n); /* in: 16-bit integer in canonical format */
/***********************************************************
The following function is used to store data in 3 consecutive
bytes. We store the most significant byte to the lowest address. */
diff --git a/innobase/include/mach0data.ic b/innobase/include/mach0data.ic
index 3ffb9baa344..888f3f743e4 100644
--- a/innobase/include/mach0data.ic
+++ b/innobase/include/mach0data.ic
@@ -68,6 +68,37 @@ mach_read_from_2(
);
}
+/************************************************************
+The following function is used to convert a 16-bit data item
+to the canonical format, for fast bytewise equality test
+against memory. */
+UNIV_INLINE
+uint16
+mach_encode_2(
+/*==========*/
+ /* out: 16-bit integer in canonical format */
+ ulint n) /* in: integer in machine-dependent format */
+{
+ uint16 ret;
+ ut_ad(2 == sizeof ret);
+ mach_write_to_2((byte*) &ret, n);
+ return(ret);
+}
+/************************************************************
+The following function is used to convert a 16-bit data item
+from the canonical format, for fast bytewise equality test
+against memory. */
+UNIV_INLINE
+ulint
+mach_decode_2(
+/*==========*/
+ /* out: integer in machine-dependent format */
+ uint16 n) /* in: 16-bit integer in canonical format */
+{
+ ut_ad(2 == sizeof n);
+ return(mach_read_from_2((byte*) &n));
+}
+
/***********************************************************
The following function is used to store data in 3 consecutive
bytes. We store the most significant byte to the lowest address. */
diff --git a/innobase/include/mem0mem.ic b/innobase/include/mem0mem.ic
index 82d88099c3f..8c87c884d78 100644
--- a/innobase/include/mem0mem.ic
+++ b/innobase/include/mem0mem.ic
@@ -623,7 +623,7 @@ mem_strdupq(
}
*d++ = q;
*d++ = '\0';
- ut_ad(len == d - dst);
+ ut_ad((ssize_t) len == d - dst);
return(dst);
}
diff --git a/innobase/include/mtr0log.h b/innobase/include/mtr0log.h
index c0636ea1e1e..6a3920aa8a1 100644
--- a/innobase/include/mtr0log.h
+++ b/innobase/include/mtr0log.h
@@ -41,10 +41,10 @@ corresponding log record to the mini-transaction log. */
void
mlog_write_string(
/*==============*/
- byte* ptr, /* in: pointer where to write */
- byte* str, /* in: string to write */
- ulint len, /* in: string length */
- mtr_t* mtr); /* in: mini-transaction handle */
+ byte* ptr, /* in: pointer where to write */
+ const byte* str, /* in: string to write */
+ ulint len, /* in: string length */
+ mtr_t* mtr); /* in: mini-transaction handle */
/************************************************************
Writes initial part of a log record consisting of one-byte item
type and four-byte space and page numbers. */
@@ -85,9 +85,9 @@ Catenates n bytes to the mtr log. */
void
mlog_catenate_string(
/*=================*/
- mtr_t* mtr, /* in: mtr */
- byte* str, /* in: string to write */
- ulint len); /* in: string length */
+ mtr_t* mtr, /* in: mtr */
+ const byte* str, /* in: string to write */
+ ulint len); /* in: string length */
/************************************************************
Catenates a compressed ulint to mlog. */
UNIV_INLINE
diff --git a/innobase/include/mtr0mtr.h b/innobase/include/mtr0mtr.h
index 071279d5259..f44e813cf6b 100644
--- a/innobase/include/mtr0mtr.h
+++ b/innobase/include/mtr0mtr.h
@@ -112,7 +112,11 @@ flag value must give the length also! */
/* mark compact clustered index
record deleted */
#define MLOG_COMP_REC_SEC_DELETE_MARK ((byte)40)/* mark compact secondary index
- record deleted */
+ record deleted; this log
+ record type is redundant, as
+ MLOG_REC_SEC_DELETE_MARK is
+ independent of the record
+ format. */
#define MLOG_COMP_REC_UPDATE_IN_PLACE ((byte)41)/* update of a compact record,
preserves record field sizes */
#define MLOG_COMP_REC_DELETE ((byte)42) /* delete a compact record
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index f55c345537e..362e3552411 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -17,6 +17,8 @@ Created 10/21/1995 Heikki Tuuri
#include <time.h>
#endif
+typedef struct fil_node_struct fil_node_t;
+
extern ibool os_do_not_call_flush_at_each_write;
extern ibool os_has_said_disk_full;
extern ibool os_aio_print_debug;
@@ -371,7 +373,7 @@ os_file_get_size_as_iblonglong(
/* out: size in bytes, -1 if error */
os_file_t file); /* in: handle to a file */
/***************************************************************************
-Sets a file size. This function can be used to extend or truncate a file. */
+Write the specified number of zeros to a newly created file. */
ibool
os_file_set_size(
@@ -563,7 +565,7 @@ os_aio(
ulint offset_high, /* in: most significant 32 bits of
offset */
ulint n, /* in: number of bytes to read or write */
- void* message1,/* in: messages for the aio handler (these
+ fil_node_t* message1,/* in: messages for the aio handler (these
can be used to identify a completed aio
operation); if mode is OS_AIO_SYNC, these
are ignored */
@@ -621,7 +623,7 @@ os_aio_windows_handle(
ignored */
ulint pos, /* this parameter is used only in sync aio:
wait for the aio slot at this position */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -641,7 +643,7 @@ os_aio_posix_handle(
/*================*/
/* out: TRUE if the aio operation succeeded */
ulint array_no, /* in: array number 0 - 3 */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -661,7 +663,7 @@ os_aio_simulated_handle(
i/o thread, segment 1 the log i/o thread,
then follow the non-ibuf read threads, and as
the last are the non-ibuf write threads */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -688,6 +690,8 @@ Refreshes the statistics used to print per-second averages. */
void
os_aio_refresh_stats(void);
/*======================*/
+
+#ifdef UNIV_DEBUG
/**************************************************************************
Checks that all slots in the system have been freed, that is, there are
no pending io operations. */
@@ -695,6 +699,7 @@ no pending io operations. */
ibool
os_aio_all_slots_free(void);
/*=======================*/
+#endif /* UNIV_DEBUG */
/***********************************************************************
This function returns information about the specified file */
diff --git a/innobase/include/page0cur.h b/innobase/include/page0cur.h
index 4fc62f37db7..e89e740e775 100644
--- a/innobase/include/page0cur.h
+++ b/innobase/include/page0cur.h
@@ -78,16 +78,16 @@ UNIV_INLINE
ibool
page_cur_is_before_first(
/*=====================*/
- /* out: TRUE if at start */
- page_cur_t* cur); /* in: cursor */
+ /* out: TRUE if at start */
+ const page_cur_t* cur); /* in: cursor */
/*************************************************************
Returns TRUE if the cursor is after last user record. */
UNIV_INLINE
ibool
page_cur_is_after_last(
/*===================*/
- /* out: TRUE if at end */
- page_cur_t* cur); /* in: cursor */
+ /* out: TRUE if at end */
+ const page_cur_t* cur); /* in: cursor */
/**************************************************************
Positions the cursor on the given record. */
UNIV_INLINE
diff --git a/innobase/include/page0cur.ic b/innobase/include/page0cur.ic
index e99d799b372..f8346819e84 100644
--- a/innobase/include/page0cur.ic
+++ b/innobase/include/page0cur.ic
@@ -69,15 +69,10 @@ UNIV_INLINE
ibool
page_cur_is_before_first(
/*=====================*/
- /* out: TRUE if at start */
- page_cur_t* cur) /* in: cursor */
+ /* out: TRUE if at start */
+ const page_cur_t* cur) /* in: cursor */
{
- if (page_get_infimum_rec(page_cur_get_page(cur)) == cur->rec) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(page_rec_is_infimum(cur->rec));
}
/*************************************************************
@@ -86,15 +81,10 @@ UNIV_INLINE
ibool
page_cur_is_after_last(
/*===================*/
- /* out: TRUE if at end */
- page_cur_t* cur) /* in: cursor */
+ /* out: TRUE if at end */
+ const page_cur_t* cur) /* in: cursor */
{
- if (page_get_supremum_rec(page_cur_get_page(cur)) == cur->rec) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(page_rec_is_supremum(cur->rec));
}
/**************************************************************
diff --git a/innobase/include/page0page.h b/innobase/include/page0page.h
index 144c297b811..c4ffa39d3ac 100644
--- a/innobase/include/page0page.h
+++ b/innobase/include/page0page.h
@@ -373,13 +373,21 @@ page_dir_find_owner_slot(
/****************************************************************
Determine whether the page is in new-style compact format. */
UNIV_INLINE
-ibool
+ulint
page_is_comp(
/*=========*/
- /* out: TRUE if the page is in compact format
- FALSE if it is in old-style format */
+ /* out: nonzero if the page is in compact
+ format, zero if it is in old-style format */
page_t* page); /* in: index page */
/****************************************************************
+TRUE if the record is on a page in compact format. */
+UNIV_INLINE
+ulint
+page_rec_is_comp(
+/*=============*/
+ /* out: nonzero if in compact format */
+ const rec_t* rec); /* in: record */
+/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
rec_t*
@@ -407,47 +415,55 @@ page_rec_get_prev(
/* out: pointer to previous record */
rec_t* rec); /* in: pointer to record,
must not be page infimum */
-
/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
-page_rec_is_user_rec(
-/*=================*/
+page_rec_is_user_rec_low(
+/*=====================*/
/* out: TRUE if a user record */
- rec_t* rec); /* in: record */
+ ulint offset);/* in: record offset on page */
/****************************************************************
TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_supremum(
-/*=================*/
+page_rec_is_supremum_low(
+/*=====================*/
/* out: TRUE if the supremum record */
- rec_t* rec); /* in: record */
+ ulint offset);/* in: record offset on page */
/****************************************************************
TRUE if the record is the infimum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_infimum(
-/*================*/
+page_rec_is_infimum_low(
+/*=====================*/
/* out: TRUE if the infimum record */
- rec_t* rec); /* in: record */
+ ulint offset);/* in: record offset on page */
+
/****************************************************************
-TRUE if the record is the first user record on the page. */
+TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
-page_rec_is_first_user_rec(
-/*=======================*/
- /* out: TRUE if first user record */
- rec_t* rec); /* in: record */
+page_rec_is_user_rec(
+/*=================*/
+ /* out: TRUE if a user record */
+ const rec_t* rec); /* in: record */
/****************************************************************
-TRUE if the record is the last user record on the page. */
+TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_last_user_rec(
-/*======================*/
- /* out: TRUE if last user record */
- rec_t* rec); /* in: record */
+page_rec_is_supremum(
+/*=================*/
+ /* out: TRUE if the supremum record */
+ const rec_t* rec); /* in: record */
+/****************************************************************
+TRUE if the record is the infimum record on a page. */
+UNIV_INLINE
+ibool
+page_rec_is_infimum(
+/*================*/
+ /* out: TRUE if the infimum record */
+ const rec_t* rec); /* in: record */
/*******************************************************************
Looks for the record which owns the given record. */
UNIV_INLINE
@@ -495,7 +511,7 @@ ulint
page_get_free_space_of_empty(
/*=========================*/
/* out: free space */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
__attribute__((const));
/****************************************************************
Returns the sum of the sizes of the records in the record list
@@ -539,7 +555,7 @@ page_create(
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
mtr_t* mtr, /* in: mini-transaction handle */
- ibool comp); /* in: TRUE=compact page format */
+ ulint comp); /* in: nonzero=compact page format */
/*****************************************************************
Differs from page_copy_rec_list_end, because this function does not
touch the lock table and max trx id on page. */
@@ -673,7 +689,7 @@ page_parse_create(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/****************************************************************
diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic
index bc0805ca30c..fd5281fdbec 100644
--- a/innobase/include/page0page.ic
+++ b/innobase/include/page0page.ic
@@ -155,14 +155,27 @@ page_header_reset_last_insert(
/****************************************************************
Determine whether the page is in new-style compact format. */
UNIV_INLINE
-ibool
+ulint
page_is_comp(
/*=========*/
- /* out: TRUE if the page is in compact format
- FALSE if it is in old-style format */
- page_t* page) /* in: index page */
+ /* out: nonzero if the page is in compact
+ format, zero if it is in old-style format */
+ page_t* page) /* in: index page */
+{
+ return(UNIV_EXPECT(page_header_get_field(page, PAGE_N_HEAP) & 0x8000,
+ 0x8000));
+}
+
+/****************************************************************
+TRUE if the record is on a page in compact format. */
+UNIV_INLINE
+ulint
+page_rec_is_comp(
+/*=============*/
+ /* out: nonzero if in compact format */
+ const rec_t* rec) /* in: record */
{
- return(!!(page_header_get_field(page, PAGE_N_HEAP) & 0x8000));
+ return(page_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE)));
}
/****************************************************************
@@ -205,112 +218,107 @@ page_get_supremum_rec(
TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
-page_rec_is_user_rec(
-/*=================*/
+page_rec_is_user_rec_low(
+/*=====================*/
/* out: TRUE if a user record */
- rec_t* rec) /* in: record */
+ ulint offset) /* in: record offset on page */
{
- ut_ad(rec);
-
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(FALSE);
- }
-
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
-
- return(FALSE);
- }
+ ut_ad(offset >= PAGE_NEW_INFIMUM);
+#if PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM
+# error "PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM"
+#endif
+#if PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM
+# error "PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM"
+#endif
+#if PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM
+# error "PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM"
+#endif
+#if PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM
+# error "PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM"
+#endif
+#if PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END
+# error "PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END"
+#endif
+#if PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END
+# error "PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END"
+#endif
+ ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
- return(TRUE);
+ return(UNIV_LIKELY(offset != PAGE_NEW_SUPREMUM)
+ && UNIV_LIKELY(offset != PAGE_NEW_INFIMUM)
+ && UNIV_LIKELY(offset != PAGE_OLD_INFIMUM)
+ && UNIV_LIKELY(offset != PAGE_OLD_SUPREMUM));
}
/****************************************************************
TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_supremum(
-/*=================*/
+page_rec_is_supremum_low(
+/*=====================*/
/* out: TRUE if the supremum record */
- rec_t* rec) /* in: record */
+ ulint offset) /* in: record offset on page */
{
- ut_ad(rec);
+ ut_ad(offset >= PAGE_NEW_INFIMUM);
+ ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(UNIV_UNLIKELY(offset == PAGE_NEW_SUPREMUM)
+ || UNIV_UNLIKELY(offset == PAGE_OLD_SUPREMUM));
}
/****************************************************************
TRUE if the record is the infimum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_infimum(
-/*================*/
+page_rec_is_infimum_low(
+/*=====================*/
/* out: TRUE if the infimum record */
- rec_t* rec) /* in: record */
+ ulint offset) /* in: record offset on page */
{
- ut_ad(rec);
-
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
-
- return(TRUE);
- }
+ ut_ad(offset >= PAGE_NEW_INFIMUM);
+ ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
- return(FALSE);
+ return(UNIV_UNLIKELY(offset == PAGE_NEW_INFIMUM)
+ || UNIV_UNLIKELY(offset == PAGE_OLD_INFIMUM));
}
/****************************************************************
-TRUE if the record is the first user record on the page. */
+TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
-page_rec_is_first_user_rec(
-/*=======================*/
- /* out: TRUE if first user record */
- rec_t* rec) /* in: record */
+page_rec_is_user_rec(
+/*=================*/
+ /* out: TRUE if a user record */
+ const rec_t* rec) /* in: record */
{
- ut_ad(rec);
-
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(FALSE);
- }
-
- if (rec == page_rec_get_next(
- page_get_infimum_rec(buf_frame_align(rec)))) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(page_rec_is_user_rec_low(
+ ut_align_offset(rec, UNIV_PAGE_SIZE)));
}
/****************************************************************
-TRUE if the record is the last user record on the page. */
+TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_last_user_rec(
-/*======================*/
- /* out: TRUE if last user record */
- rec_t* rec) /* in: record */
+page_rec_is_supremum(
+/*=================*/
+ /* out: TRUE if the supremum record */
+ const rec_t* rec) /* in: record */
{
- ut_ad(rec);
-
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(FALSE);
- }
-
- if (page_rec_get_next(rec)
- == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(TRUE);
- }
+ return(page_rec_is_supremum_low(
+ ut_align_offset(rec, UNIV_PAGE_SIZE)));
+}
- return(FALSE);
+/****************************************************************
+TRUE if the record is the infimum record on a page. */
+UNIV_INLINE
+ibool
+page_rec_is_infimum(
+/*================*/
+ /* out: TRUE if the infimum record */
+ const rec_t* rec) /* in: record */
+{
+ return(page_rec_is_infimum_low(
+ ut_align_offset(rec, UNIV_PAGE_SIZE)));
}
/*****************************************************************
@@ -340,22 +348,26 @@ page_cmp_dtuple_rec_with_match(
matched; when function returns contains the
value for current comparison */
{
- page_t* page;
+ ulint rec_offset;
ut_ad(dtuple_check_typed(dtuple));
ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec));
- page = buf_frame_align(rec);
+ rec_offset = ut_align_offset(rec, UNIV_PAGE_SIZE);
- if (rec == page_get_infimum_rec(page)) {
+ if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_INFIMUM)
+ || UNIV_UNLIKELY(rec_offset == PAGE_OLD_INFIMUM)) {
return(1);
- } else if (rec == page_get_supremum_rec(page)) {
+ }
+ if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_SUPREMUM)
+ || UNIV_UNLIKELY(rec_offset == PAGE_OLD_SUPREMUM)) {
return(-1);
- } else {
- return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
+ }
+
+ return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
matched_fields,
matched_bytes));
- }
}
/*****************************************************************
@@ -482,7 +494,7 @@ page_dir_slot_set_rec(
{
ut_ad(page_rec_check(rec));
- mach_write_to_2(slot, rec - buf_frame_align(rec));
+ mach_write_to_2(slot, ut_align_offset(rec, UNIV_PAGE_SIZE));
}
/*******************************************************************
@@ -494,8 +506,8 @@ page_dir_slot_get_n_owned(
/* out: number of records */
page_dir_slot_t* slot) /* in: page directory slot */
{
- return(rec_get_n_owned(page_dir_slot_get_rec(slot),
- page_is_comp(buf_frame_align(slot))));
+ rec_t* rec = page_dir_slot_get_rec(slot);
+ return(rec_get_n_owned(rec, page_rec_is_comp(rec)));
}
/*******************************************************************
@@ -508,8 +520,8 @@ page_dir_slot_set_n_owned(
ulint n) /* in: number of records owned
by the slot */
{
- rec_set_n_owned(page_dir_slot_get_rec(slot),
- page_is_comp(buf_frame_align(slot)), n);
+ rec_t* rec = page_dir_slot_get_rec(slot);
+ rec_set_n_owned(rec, page_rec_is_comp(rec), n);
}
/****************************************************************
@@ -540,26 +552,25 @@ page_rec_get_next(
ut_ad(page_rec_check(rec));
- page = buf_frame_align(rec);
+ page = ut_align_down(rec, UNIV_PAGE_SIZE);
offs = rec_get_next_offs(rec, page_is_comp(page));
- if (offs >= UNIV_PAGE_SIZE) {
- fprintf(stderr,
-"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n",
- (ulong)offs, (ulong)(rec - page));
+ if (UNIV_UNLIKELY(offs >= UNIV_PAGE_SIZE)) {
fprintf(stderr,
-"\nInnoDB: rec address %p, first buffer frame %p\n"
+"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n"
+"InnoDB: rec address %p, first buffer frame %p\n"
"InnoDB: buffer pool high end %p, buf fix count %lu\n",
+ (ulong)offs, (ulong)(rec - page),
rec, buf_pool->frame_zero,
buf_pool->high_end,
(ulong)buf_block_align(rec)->buf_fix_count);
buf_page_print(page);
- ut_a(0);
+ ut_error;
}
- if (offs == 0) {
+ if (UNIV_UNLIKELY(offs == 0)) {
return(NULL);
}
@@ -581,15 +592,12 @@ page_rec_set_next(
ulint offs;
ut_ad(page_rec_check(rec));
- ut_a((next == NULL)
- || (buf_frame_align(rec) == buf_frame_align(next)));
-
- page = buf_frame_align(rec);
-
- ut_ad(rec != page_get_supremum_rec(page));
- ut_ad(next != page_get_infimum_rec(page));
+ ut_ad(!page_rec_is_supremum(rec));
+ page = ut_align_down(rec, UNIV_PAGE_SIZE);
if (next) {
+ ut_ad(!page_rec_is_infimum(next));
+ ut_ad(page == ut_align_down(next, UNIV_PAGE_SIZE));
offs = (ulint) (next - page);
} else {
offs = 0;
@@ -613,13 +621,12 @@ page_rec_get_prev(
rec_t* rec2;
rec_t* prev_rec = NULL;
page_t* page;
- ibool comp;
ut_ad(page_rec_check(rec));
- page = buf_frame_align(rec);
+ page = ut_align_down(rec, UNIV_PAGE_SIZE);
- ut_ad(rec != page_get_infimum_rec(page));
+ ut_ad(!page_rec_is_infimum(rec));
slot_no = page_dir_find_owner_slot(rec);
@@ -628,7 +635,6 @@ page_rec_get_prev(
slot = page_dir_get_nth_slot(page, slot_no - 1);
rec2 = page_dir_slot_get_rec(slot);
- comp = page_is_comp(page);
while (rec != rec2) {
prev_rec = rec2;
@@ -649,13 +655,16 @@ page_rec_find_owner_rec(
/* out: the owner record */
rec_t* rec) /* in: the physical record */
{
- ibool comp;
-
ut_ad(page_rec_check(rec));
- comp = page_is_comp(buf_frame_align(rec));
- while (rec_get_n_owned(rec, comp) == 0) {
- rec = page_rec_get_next(rec);
+ if (page_rec_is_comp(rec)) {
+ while (rec_get_n_owned(rec, TRUE) == 0) {
+ rec = page_rec_get_next(rec);
+ }
+ } else {
+ while (rec_get_n_owned(rec, FALSE) == 0) {
+ rec = page_rec_get_next(rec);
+ }
}
return(rec);
@@ -691,10 +700,17 @@ ulint
page_get_free_space_of_empty(
/*=========================*/
/* out: free space */
- ibool comp) /* in: TRUE=compact page layout */
+ ulint comp) /* in: nonzero=compact page layout */
{
+ if (UNIV_LIKELY(comp)) {
+ return((ulint)(UNIV_PAGE_SIZE
+ - PAGE_NEW_SUPREMUM_END
+ - PAGE_DIR
+ - 2 * PAGE_DIR_SLOT_SIZE));
+ }
+
return((ulint)(UNIV_PAGE_SIZE
- - (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
+ - PAGE_OLD_SUPREMUM_END
- PAGE_DIR
- 2 * PAGE_DIR_SLOT_SIZE));
}
@@ -716,17 +732,21 @@ page_get_max_insert_size(
{
ulint occupied;
ulint free_space;
- ibool comp;
- comp = page_is_comp(page);
+ if (page_is_comp(page)) {
+ occupied = page_header_get_field(page, PAGE_HEAP_TOP)
+ - PAGE_NEW_SUPREMUM_END + page_dir_calc_reserved_space(
+ n_recs + page_dir_get_n_heap(page) - 2);
- occupied = page_header_get_field(page, PAGE_HEAP_TOP)
- - (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
- + page_dir_calc_reserved_space(
+ free_space = page_get_free_space_of_empty(TRUE);
+ } else {
+ occupied = page_header_get_field(page, PAGE_HEAP_TOP)
+ - PAGE_OLD_SUPREMUM_END + page_dir_calc_reserved_space(
n_recs + page_dir_get_n_heap(page) - 2);
- free_space = page_get_free_space_of_empty(comp);
-
+ free_space = page_get_free_space_of_empty(FALSE);
+ }
+
/* Above the 'n_recs +' part reserves directory space for the new
inserted records; the '- 2' excludes page infimum and supremum
records */
@@ -752,14 +772,11 @@ page_get_max_insert_size_after_reorganize(
{
ulint occupied;
ulint free_space;
- ibool comp;
- comp = page_is_comp(page);
-
occupied = page_get_data_size(page)
+ page_dir_calc_reserved_space(n_recs + page_get_n_recs(page));
- free_space = page_get_free_space_of_empty(comp);
+ free_space = page_get_free_space_of_empty(page_is_comp(page));
if (occupied > free_space) {
@@ -783,6 +800,7 @@ page_mem_free(
ulint garbage;
ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec));
free = page_header_get_ptr(page, PAGE_FREE);
page_rec_set_next(rec, free);
diff --git a/innobase/include/read0read.ic b/innobase/include/read0read.ic
index 03d84ee0c51..ec9ef5814bb 100644
--- a/innobase/include/read0read.ic
+++ b/innobase/include/read0read.ic
@@ -71,13 +71,8 @@ read_view_sees_trx_id(
cmp = ut_dulint_cmp(trx_id,
read_view_get_nth_trx_id(view, n_ids - i - 1));
- if (0 == cmp) {
-
- return(FALSE);
-
- } else if (cmp < 0) {
-
- return(TRUE);
+ if (cmp <= 0) {
+ return(cmp < 0);
}
}
diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h
index 134c37c8030..1d15b8d1c77 100644
--- a/innobase/include/rem0rec.h
+++ b/innobase/include/rem0rec.h
@@ -51,7 +51,7 @@ rec_get_next_offs(
/* out: the page offset of the next
chained record */
rec_t* rec, /* in: physical record */
- ibool comp); /* in: TRUE=compact page format */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the next record offset field
of the record. */
@@ -60,7 +60,7 @@ void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint next); /* in: offset of the next record */
/**********************************************************
The following function is used to get the number of fields
@@ -90,7 +90,7 @@ rec_get_n_owned(
/*============*/
/* out: number of owned records */
rec_t* rec, /* in: physical record */
- ibool comp); /* in: TRUE=compact page format */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the number of owned
records. */
@@ -99,7 +99,7 @@ void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint n_owned); /* in: the number of owned */
/**********************************************************
The following function is used to retrieve the info bits of
@@ -110,7 +110,7 @@ rec_get_info_bits(
/*==============*/
/* out: info bits */
rec_t* rec, /* in: physical record */
- ibool comp); /* in: TRUE=compact page format */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the info bits of a record. */
UNIV_INLINE
@@ -118,7 +118,7 @@ void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint bits); /* in: info bits */
/**********************************************************
The following function retrieves the status bits of a new-style record. */
@@ -147,7 +147,7 @@ rec_get_info_and_status_bits(
/*=========================*/
/* out: info bits */
rec_t* rec, /* in: physical record */
- ibool comp); /* in: TRUE=compact page format */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the info and status
bits of a record. (Only compact records have status bits.) */
@@ -156,18 +156,18 @@ void
rec_set_info_and_status_bits(
/*=========================*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint bits); /* in: info bits */
/**********************************************************
The following function tells if record is delete marked. */
UNIV_INLINE
-ibool
+ulint
rec_get_deleted_flag(
/*=================*/
- /* out: TRUE if delete marked */
+ /* out: nonzero if delete marked */
rec_t* rec, /* in: physical record */
- ibool comp); /* in: TRUE=compact page format */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the deleted bit. */
UNIV_INLINE
@@ -175,8 +175,8 @@ void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
- ibool flag); /* in: TRUE if delete marked */
+ ulint comp, /* in: nonzero=compact page format */
+ ulint flag); /* in: nonzero if delete marked */
/**********************************************************
The following function tells if a new-style record is a node pointer. */
UNIV_INLINE
@@ -186,14 +186,6 @@ rec_get_node_ptr_flag(
/* out: TRUE if node pointer */
rec_t* rec); /* in: physical record */
/**********************************************************
-The following function is used to flag a record as a node pointer. */
-UNIV_INLINE
-void
-rec_set_node_ptr_flag(
-/*=================*/
- rec_t* rec, /* in: physical record */
- ibool flag); /* in: TRUE if the record is a node pointer */
-/**********************************************************
The following function is used to get the order number
of the record in the heap of the index page. */
UNIV_INLINE
@@ -202,7 +194,7 @@ rec_get_heap_no(
/*=============*/
/* out: heap order number */
rec_t* rec, /* in: physical record */
- ibool comp); /* in: TRUE=compact page format */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the heap number
field in the record. */
@@ -211,7 +203,7 @@ void
rec_set_heap_no(
/*=============*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint heap_no);/* in: the heap number */
/**********************************************************
The following function is used to test whether the data offsets
@@ -290,7 +282,7 @@ rec_get_nth_field_size(
ulint n); /* in: index of the field */
/****************************************************************
The following function is used to get a pointer to the nth
-data field in an old-style record. */
+data field in a record. */
UNIV_INLINE
byte*
rec_get_nth_field(
@@ -305,27 +297,18 @@ rec_get_nth_field(
Determine if the offsets are for a record in the new
compact format. */
UNIV_INLINE
-ibool
+ulint
rec_offs_comp(
/*==========*/
- /* out: TRUE if compact format */
+ /* out: nonzero if compact format */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**********************************************************
-Returns TRUE if the nth field of rec is SQL NULL. */
+Returns nonzero if the extern bit is set in nth field of rec. */
UNIV_INLINE
-ibool
-rec_offs_nth_null(
-/*==============*/
- /* out: TRUE if SQL NULL */
- const ulint* offsets,/* in: array returned by rec_get_offsets() */
- ulint n); /* in: nth field */
-/**********************************************************
-Returns TRUE if the extern bit is set in nth field of rec. */
-UNIV_INLINE
-ibool
+ulint
rec_offs_nth_extern(
/*================*/
- /* out: TRUE if externally stored */
+ /* out: nonzero if externally stored */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint n); /* in: nth field */
/**********************************************************
diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic
index 2593fb8edeb..e2dceb6bae5 100644
--- a/innobase/include/rem0rec.ic
+++ b/innobase/include/rem0rec.ic
@@ -265,7 +265,7 @@ rec_get_next_offs(
/* out: the page offset of the next chained record, or
0 if none */
rec_t* rec, /* in: physical record */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
{
ulint field_value;
@@ -312,7 +312,7 @@ void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint next) /* in: offset of the next record, or 0 if none */
{
ut_ad(rec);
@@ -414,7 +414,7 @@ rec_get_n_fields(
{
ut_ad(rec);
ut_ad(index);
- if (!index->table->comp) {
+ if (UNIV_UNLIKELY(!index->table->comp)) {
return(rec_get_n_fields_old(rec));
}
switch (rec_get_status(rec)) {
@@ -440,7 +440,7 @@ rec_get_n_owned(
/*============*/
/* out: number of owned records */
rec_t* rec, /* in: physical record */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
{
ulint ret;
@@ -461,7 +461,7 @@ void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint n_owned) /* in: the number of owned */
{
ut_ad(rec);
@@ -480,7 +480,7 @@ rec_get_info_bits(
/*==============*/
/* out: info bits */
rec_t* rec, /* in: physical record */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
{
ulint ret;
@@ -501,7 +501,7 @@ void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint bits) /* in: info bits */
{
ut_ad(rec);
@@ -537,14 +537,14 @@ rec_get_info_and_status_bits(
/*=========================*/
/* out: info bits */
rec_t* rec, /* in: physical record */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
{
ulint bits;
#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)
# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap"
#endif
- if (comp) {
+ if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec);
} else {
bits = rec_get_info_bits(rec, FALSE);
@@ -560,7 +560,7 @@ void
rec_set_info_and_status_bits(
/*=========================*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint bits) /* in: info bits */
{
#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
@@ -578,19 +578,22 @@ rec_set_info_and_status_bits(
/**********************************************************
The following function tells if record is delete marked. */
UNIV_INLINE
-ibool
+ulint
rec_get_deleted_flag(
/*=================*/
- /* out: TRUE if delete marked */
+ /* out: nonzero if delete marked */
rec_t* rec, /* in: physical record */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
{
- if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec, comp)) {
-
- return(TRUE);
+ if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
+ return(UNIV_UNLIKELY(rec_get_bit_field_1(rec,
+ REC_NEW_INFO_BITS, REC_INFO_DELETED_FLAG,
+ REC_INFO_BITS_SHIFT)));
+ } else {
+ return(UNIV_UNLIKELY(rec_get_bit_field_1(rec,
+ REC_OLD_INFO_BITS, REC_INFO_DELETED_FLAG,
+ REC_INFO_BITS_SHIFT)));
}
-
- return(FALSE);
}
/**********************************************************
@@ -600,24 +603,20 @@ void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
- ibool flag) /* in: TRUE if delete marked */
+ ulint comp, /* in: nonzero=compact page format */
+ ulint flag) /* in: nonzero if delete marked */
{
- ulint old_val;
- ulint new_val;
-
- ut_ad(TRUE == 1);
- ut_ad(flag <= TRUE);
+ ulint val;
- old_val = rec_get_info_bits(rec, comp);
+ val = rec_get_info_bits(rec, comp);
if (flag) {
- new_val = REC_INFO_DELETED_FLAG | old_val;
+ val |= REC_INFO_DELETED_FLAG;
} else {
- new_val = ~REC_INFO_DELETED_FLAG & old_val;
+ val &= ~REC_INFO_DELETED_FLAG;
}
- rec_set_info_bits(rec, comp, new_val);
+ rec_set_info_bits(rec, comp, val);
}
/**********************************************************
@@ -633,26 +632,6 @@ rec_get_node_ptr_flag(
}
/**********************************************************
-The following function is used to flag a record as a node pointer. */
-UNIV_INLINE
-void
-rec_set_node_ptr_flag(
-/*=================*/
- rec_t* rec, /* in: physical record */
- ibool flag) /* in: TRUE if the record is a node pointer */
-{
- ulint status;
- ut_ad(flag <= TRUE);
- ut_ad(REC_STATUS_NODE_PTR >= rec_get_status(rec));
- if (flag) {
- status = REC_STATUS_NODE_PTR;
- } else {
- status = REC_STATUS_ORDINARY;
- }
- rec_set_status(rec, status);
-}
-
-/**********************************************************
The following function is used to get the order number of the record in the
heap of the index page. */
UNIV_INLINE
@@ -661,7 +640,7 @@ rec_get_heap_no(
/*=============*/
/* out: heap order number */
rec_t* rec, /* in: physical record */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
{
ulint ret;
@@ -682,7 +661,7 @@ void
rec_set_heap_no(
/*=============*/
rec_t* rec, /* in: physical record */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
ulint heap_no)/* in: the heap number */
{
ut_ad(heap_no <= REC_MAX_HEAP_NO);
@@ -843,7 +822,7 @@ rec_offs_validate(
{
ulint i = rec_offs_n_fields(offsets);
ulint last = ULINT_MAX;
- ibool comp = (*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0;
+ ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT;
if (rec) {
ut_ad((ulint) rec == offsets[2]);
@@ -907,7 +886,7 @@ rec_offs_make_valid(
/****************************************************************
The following function is used to get a pointer to the nth
-data field in an old-style record. */
+data field in a record. */
UNIV_INLINE
byte*
rec_get_nth_field(
@@ -926,7 +905,7 @@ rec_get_nth_field(
ut_ad(n < rec_offs_n_fields(offsets));
ut_ad(len);
- if (n == 0) {
+ if (UNIV_UNLIKELY(n == 0)) {
field = rec;
} else {
field = rec + (rec_offs_base(offsets)[n] & REC_OFFS_MASK);
@@ -949,43 +928,30 @@ rec_get_nth_field(
Determine if the offsets are for a record in the new
compact format. */
UNIV_INLINE
-ibool
+ulint
rec_offs_comp(
/*==========*/
- /* out: TRUE if compact format */
+ /* out: nonzero if compact format */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ut_ad(rec_offs_validate(NULL, NULL, offsets));
- return((*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0);
+ return(*rec_offs_base(offsets) & REC_OFFS_COMPACT);
}
/**********************************************************
-Returns TRUE if the nth field of rec is SQL NULL. */
-UNIV_INLINE
-ibool
-rec_offs_nth_null(
-/*==============*/
- /* out: TRUE if SQL NULL */
- const ulint* offsets,/* in: array returned by rec_get_offsets() */
- ulint n) /* in: nth field */
-{
- ut_ad(rec_offs_validate(NULL, NULL, offsets));
- ut_ad(n < rec_offs_n_fields(offsets));
- return((rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL) != 0);
-}
-/**********************************************************
-Returns TRUE if the extern bit is set in nth field of rec. */
+Returns nonzero if the extern bit is set in nth field of rec. */
UNIV_INLINE
-ibool
+ulint
rec_offs_nth_extern(
/*================*/
- /* out: TRUE if externally stored */
+ /* out: nonzero if externally stored */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint n) /* in: nth field */
{
ut_ad(rec_offs_validate(NULL, NULL, offsets));
ut_ad(n < rec_offs_n_fields(offsets));
- return((rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL) != 0);
+ return(UNIV_UNLIKELY(rec_offs_base(offsets)[1 + n]
+ & REC_OFFS_EXTERNAL));
}
/**********************************************************
@@ -1037,7 +1003,7 @@ rec_set_nth_field_extern_bit(
where rec is, or NULL; in the NULL case
we do not write to log about the change */
{
- if (index->table->comp) {
+ if (UNIV_LIKELY(index->table->comp)) {
rec_set_nth_field_extern_bit_new(rec, index, i, val, mtr);
} else {
rec_set_nth_field_extern_bit_old(rec, i, val, mtr);
@@ -1048,7 +1014,7 @@ rec_set_nth_field_extern_bit(
Returns the offset of n - 1th field end if the record is stored in the 1-byte
offsets form. If the field is SQL null, the flag is ORed in the returned
value. This function and the 2-byte counterpart are defined here because the
-C-compilerwas not able to sum negative and positive constant offsets, and
+C-compiler was not able to sum negative and positive constant offsets, and
warned of constant arithmetic overflow within the compiler. */
UNIV_INLINE
ulint
@@ -1452,7 +1418,7 @@ rec_get_converted_size(
? dict_index_get_n_unique_in_tree(index) + 1
: dict_index_get_n_fields(index)));
- if (index->table->comp) {
+ if (UNIV_LIKELY(index->table->comp)) {
return(rec_get_converted_size_new(index, dtuple));
}
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index e44d689b88b..4bb9fa63cd1 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -110,7 +110,7 @@ row_mysql_store_col_in_innobase_format(
necessarily the length of the actual
payload data; if the column is a true
VARCHAR then this is irrelevant */
- ibool comp); /* in: TRUE = compact format */
+ ulint comp); /* in: nonzero=compact format */
/********************************************************************
Handles user errors and lock waits detected by the database engine. */
@@ -172,14 +172,6 @@ row_lock_table_autoinc_for_mysql(
row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL
table handle */
/*************************************************************************
-Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
-lock type LOCK_TABLE_EXP). */
-
-void
-row_unlock_tables_for_mysql(
-/*========================*/
- trx_t* trx); /* in: transaction */
-/*************************************************************************
Sets a table lock on the table mentioned in prebuilt. */
int
@@ -190,9 +182,10 @@ row_lock_table_for_mysql(
table handle */
dict_table_t* table, /* in: table to lock, or NULL
if prebuilt->table should be
- locked as LOCK_TABLE_EXP |
+ locked as
prebuilt->select_lock_type */
- ulint mode); /* in: lock mode of table */
+ ulint mode); /* in: lock mode of table
+ (ignored if table==NULL) */
/*************************************************************************
Does an insert for MySQL. */
@@ -599,6 +592,8 @@ struct row_prebuilt_struct {
that was decided in ha_innodb.cc,
::store_lock(), ::external_lock(),
etc. */
+ ulint mysql_prefix_len;/* byte offset of the end of
+ the last requested column */
ulint mysql_row_len; /* length in bytes of a row in the
MySQL format */
ulint n_rows_fetched; /* number of rows fetched after
diff --git a/innobase/include/row0sel.ic b/innobase/include/row0sel.ic
index 595cea1138b..600c6204571 100644
--- a/innobase/include/row0sel.ic
+++ b/innobase/include/row0sel.ic
@@ -75,7 +75,7 @@ open_step(
}
}
- if (err != DB_SUCCESS) {
+ if (UNIV_EXPECT(err, DB_SUCCESS) != DB_SUCCESS) {
/* SQL error detected */
fprintf(stderr, "SQL error %lu\n", (ulong) err);
diff --git a/innobase/include/row0upd.ic b/innobase/include/row0upd.ic
index e2d81a39cfa..acbb11aa1c7 100644
--- a/innobase/include/row0upd.ic
+++ b/innobase/include/row0upd.ic
@@ -83,7 +83,7 @@ upd_field_set_field_no(
{
upd_field->field_no = field_no;
- if (field_no >= dict_index_get_n_fields(index)) {
+ if (UNIV_UNLIKELY(field_no >= dict_index_get_n_fields(index))) {
fprintf(stderr,
"InnoDB: Error: trying to access field %lu in ",
(ulong) field_no);
diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
index 3a92100ba01..b1ae636010a 100644
--- a/innobase/include/sync0rw.ic
+++ b/innobase/include/sync0rw.ic
@@ -138,7 +138,7 @@ rw_lock_s_lock_low(
#endif /* UNIV_SYNC_DEBUG */
/* Check if the writer field is free */
- if (lock->writer == RW_LOCK_NOT_LOCKED) {
+ if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) {
/* Set the shared lock by incrementing the reader count */
lock->reader_count++;
@@ -243,7 +243,7 @@ rw_lock_s_lock_func(
mutex_enter(rw_lock_get_mutex(lock));
- if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
+ if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) {
mutex_exit(rw_lock_get_mutex(lock));
return; /* Success */
@@ -307,21 +307,18 @@ rw_lock_x_lock_func_nowait(
const char* file_name,/* in: file name where lock requested */
ulint line) /* in: line where requested */
{
- ibool success = FALSE;
-
+ ibool success = FALSE;
+ os_thread_id_t curr_thread = os_thread_get_curr_id();
mutex_enter(rw_lock_get_mutex(lock));
- if ((rw_lock_get_reader_count(lock) == 0)
- && ((rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)
- || ((rw_lock_get_writer(lock) == RW_LOCK_EX)
- && (lock->pass == 0)
- && os_thread_eq(lock->writer_thread,
- os_thread_get_curr_id())))) {
-
+ if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) {
+ } else if (UNIV_LIKELY(rw_lock_get_writer(lock)
+ == RW_LOCK_NOT_LOCKED)) {
rw_lock_set_writer(lock, RW_LOCK_EX);
- lock->writer_thread = os_thread_get_curr_id();
- lock->writer_count++;
+ lock->writer_thread = curr_thread;
lock->pass = 0;
+ relock:
+ lock->writer_count++;
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
@@ -331,6 +328,10 @@ rw_lock_x_lock_func_nowait(
lock->last_x_line = line;
success = TRUE;
+ } else if (rw_lock_get_writer(lock) == RW_LOCK_EX
+ && lock->pass == 0
+ && os_thread_eq(lock->writer_thread, curr_thread)) {
+ goto relock;
}
mutex_exit(rw_lock_get_mutex(lock));
@@ -361,7 +362,7 @@ rw_lock_s_unlock_func(
/* Reset the shared lock by decrementing the reader count */
- ut_a(lock->reader_count > 0);
+ ut_ad(lock->reader_count > 0);
lock->reader_count--;
#ifdef UNIV_SYNC_DEBUG
@@ -371,7 +372,8 @@ rw_lock_s_unlock_func(
/* If there may be waiters and this was the last s-lock,
signal the object */
- if (lock->waiters && (lock->reader_count == 0)) {
+ if (UNIV_UNLIKELY(lock->waiters)
+ && lock->reader_count == 0) {
sg = TRUE;
rw_lock_set_waiters(lock, 0);
@@ -379,7 +381,7 @@ rw_lock_s_unlock_func(
mutex_exit(mutex);
- if (sg == TRUE) {
+ if (UNIV_UNLIKELY(sg)) {
sync_array_signal_object(sync_primary_wait_array, lock);
}
@@ -450,7 +452,8 @@ rw_lock_x_unlock_func(
#endif
/* If there may be waiters, signal the lock */
- if (lock->waiters && (lock->writer_count == 0)) {
+ if (UNIV_UNLIKELY(lock->waiters)
+ && lock->writer_count == 0) {
sg = TRUE;
rw_lock_set_waiters(lock, 0);
@@ -458,7 +461,7 @@ rw_lock_x_unlock_func(
mutex_exit(&(lock->mutex));
- if (sg == TRUE) {
+ if (UNIV_UNLIKELY(sg)) {
sync_array_signal_object(sync_primary_wait_array, lock);
}
diff --git a/innobase/include/trx0rseg.ic b/innobase/include/trx0rseg.ic
index 35e927f5e79..c9ac50ebf16 100644
--- a/innobase/include/trx0rseg.ic
+++ b/innobase/include/trx0rseg.ic
@@ -65,7 +65,7 @@ trx_rsegf_get_nth_undo(
ulint n, /* in: index of slot */
mtr_t* mtr) /* in: mtr */
{
- if (n >= TRX_RSEG_N_SLOTS) {
+ if (UNIV_UNLIKELY(n >= TRX_RSEG_N_SLOTS)) {
fprintf(stderr,
"InnoDB: Error: trying to get slot %lu of rseg\n", (unsigned long) n);
ut_error;
@@ -86,7 +86,7 @@ trx_rsegf_set_nth_undo(
ulint page_no,/* in: page number of the undo log segment */
mtr_t* mtr) /* in: mtr */
{
- if (n >= TRX_RSEG_N_SLOTS) {
+ if (UNIV_UNLIKELY(n >= TRX_RSEG_N_SLOTS)) {
fprintf(stderr,
"InnoDB: Error: trying to set slot %lu of rseg\n", (unsigned long) n);
ut_error;
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index d46613c3a68..8df50d6703d 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -312,6 +312,19 @@ trx_print(
FILE* f, /* in: output stream */
trx_t* trx); /* in: transaction */
+#ifndef UNIV_HOTBACKUP
+/**************************************************************************
+Determines if the currently running transaction has been interrupted. */
+
+ibool
+trx_is_interrupted(
+/*===============*/
+ /* out: TRUE if interrupted */
+ trx_t* trx); /* in: transaction */
+#else /* !UNIV_HOTBACKUP */
+#define trx_is_interrupted(trx) FALSE
+#endif /* !UNIV_HOTBACKUP */
+
/* Signal to a transaction */
struct trx_sig_struct{
@@ -484,13 +497,6 @@ struct trx_struct{
in the lock list trx_locks */
ibool trx_create_lock;/* this is TRUE if we have created a
new lock for a record accessed */
- ulint n_lock_table_exp;/* number of explicit table locks
- (LOCK TABLES) reserved by the
- transaction, stored in trx_locks */
- ulint n_lock_table_transactional;
- /* number of transactional table locks
- (LOCK TABLES..WHERE ENGINE) reserved by
- the transaction, stored in trx_locks */
UT_LIST_NODE_T(trx_t)
trx_list; /* list of transactions */
UT_LIST_NODE_T(trx_t)
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index 8158c198e21..132ac9e18c5 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -181,7 +181,7 @@ management to ensure correct alignment for doubles etc. */
/* Another basic type we use is unsigned long integer which should be equal to
the word size of the machine, that is on a 32-bit platform 32 bits, and on a
64-bit platform 64 bits. We also give the printf format for the type as a
-macro PRULINT. */
+macro ULINTPF. */
#ifdef _WIN64
typedef unsigned __int64 ulint;
@@ -243,6 +243,30 @@ contains the sum of the following flag and the locally stored len. */
#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE)
+/* Some macros to improve branch prediction and reduce cache misses */
+#if defined(__GNUC__) && (__GNUC__ > 2)
+/* Tell the compiler that 'expr' probably evaluates to 'constant'. */
+# define UNIV_EXPECT(expr,constant) __builtin_expect(expr, constant)
+/* Tell the compiler that a pointer is likely to be NULL */
+# define UNIV_LIKELY_NULL(ptr) __builtin_expect((ulint) ptr, 0)
+/* Minimize cache-miss latency by moving data at addr into a cache before
+it is read. */
+# define UNIV_PREFETCH_R(addr) __builtin_prefetch(addr, 0, 3)
+/* Minimize cache-miss latency by moving data at addr into a cache before
+it is read or written. */
+# define UNIV_PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 3)
+#else
+/* Dummy versions of the macros */
+# define UNIV_EXPECT(expr,value) (expr)
+# define UNIV_LIKELY_NULL(expr) (expr)
+# define UNIV_PREFETCH_R(addr) ((void) 0)
+# define UNIV_PREFETCH_RW(addr) ((void) 0)
+#endif
+/* Tell the compiler that cond is likely to hold */
+#define UNIV_LIKELY(cond) UNIV_EXPECT(cond, TRUE)
+/* Tell the compiler that cond is unlikely to hold */
+#define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE)
+
#include <stdio.h>
#include "ut0dbg.h"
#include "ut0ut.h"
diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h
index 5f30a894874..bc3f852626a 100644
--- a/innobase/include/ut0dbg.h
+++ b/innobase/include/ut0dbg.h
@@ -13,74 +13,75 @@ Created 1/30/1994 Heikki Tuuri
#include <stdlib.h>
#include "os0thread.h"
+#if defined(__GNUC__) && (__GNUC__ > 2)
+# define UT_DBG_FAIL(EXPR) UNIV_UNLIKELY(!((ulint)(EXPR)))
+#else
extern ulint ut_dbg_zero; /* This is used to eliminate
compiler warnings */
+# define UT_DBG_FAIL(EXPR) !((ulint)(EXPR) + ut_dbg_zero)
+#endif
+
+/*****************************************************************
+Report a failed assertion. */
+
+void
+ut_dbg_assertion_failed(
+/*====================*/
+ const char* expr, /* in: the failed assertion */
+ const char* file, /* in: source file containing the assertion */
+ ulint line); /* in: line number of the assertion */
+
+#ifdef __NETWARE__
+/* Flag for ignoring further assertion failures.
+On NetWare, have a graceful exit rather than a segfault to avoid abends. */
+extern ibool panic_shutdown;
+/* Abort the execution. */
+void ut_dbg_panic(void);
+# define UT_DBG_PANIC ut_dbg_panic()
+/* Stop threads in ut_a(). */
+# define UT_DBG_STOP while (0) /* We do not do this on NetWare */
+#else /* __NETWARE__ */
+/* Flag for indicating that all threads should stop. This will be set
+by ut_dbg_assertion_failed(). */
extern ibool ut_dbg_stop_threads;
+/* A null pointer that will be dereferenced to trigger a memory trap */
extern ulint* ut_dbg_null_ptr;
-extern const char* ut_dbg_msg_assert_fail;
-extern const char* ut_dbg_msg_trap;
-extern const char* ut_dbg_msg_stop;
-/* Have a graceful exit on NetWare rather than a segfault to avoid abends */
-#ifdef __NETWARE__
-extern ibool panic_shutdown;
-#define ut_a(EXPR) do {\
- if (!((ulint)(EXPR) + ut_dbg_zero)) {\
- ut_print_timestamp(stderr);\
- fprintf(stderr, ut_dbg_msg_assert_fail,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__,\
- (ulint)__LINE__);\
- fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\
- fputs(ut_dbg_msg_trap, stderr);\
- ut_dbg_stop_threads = TRUE;\
- if (ut_dbg_stop_threads) {\
- fprintf(stderr, ut_dbg_msg_stop,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
- }\
- if(!panic_shutdown){\
- panic_shutdown = TRUE;\
- innobase_shutdown_for_mysql();}\
- exit(1);\
- }\
-} while (0)
-#define ut_error do {\
- ut_print_timestamp(stderr);\
- fprintf(stderr, ut_dbg_msg_assert_fail,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
- fprintf(stderr, ut_dbg_msg_trap);\
- ut_dbg_stop_threads = TRUE;\
- if(!panic_shutdown){panic_shutdown = TRUE;\
- innobase_shutdown_for_mysql();}\
-} while (0)
-#else
-#define ut_a(EXPR) do {\
- if (!((ulint)(EXPR) + ut_dbg_zero)) {\
- ut_print_timestamp(stderr);\
- fprintf(stderr, ut_dbg_msg_assert_fail,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__,\
- (ulint)__LINE__);\
- fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\
- fputs(ut_dbg_msg_trap, stderr);\
- ut_dbg_stop_threads = TRUE;\
- 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()), __FILE__, (ulint)__LINE__);\
- os_thread_sleep(1000000000);\
- }\
+/*****************************************************************
+Stop a thread after assertion failure. */
+
+void
+ut_dbg_stop_thread(
+/*===============*/
+ const char* file,
+ ulint line);
+
+/* Abort the execution. */
+# define UT_DBG_PANIC \
+ if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL
+/* Stop threads in ut_a(). */
+# define UT_DBG_STOP do \
+ if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \
+ ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \
+ } while (0)
+#endif /* __NETWARE__ */
+
+/* Abort execution if EXPR does not evaluate to nonzero. */
+#define ut_a(EXPR) do { \
+ if (UT_DBG_FAIL(EXPR)) { \
+ ut_dbg_assertion_failed(#EXPR, \
+ __FILE__, (ulint) __LINE__); \
+ UT_DBG_PANIC; \
+ } \
+ UT_DBG_STOP; \
} while (0)
-#define ut_error do {\
- ut_print_timestamp(stderr);\
- fprintf(stderr, ut_dbg_msg_assert_fail,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
- fprintf(stderr, ut_dbg_msg_trap);\
- ut_dbg_stop_threads = TRUE;\
- if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\
+/* Abort execution. */
+#define ut_error do { \
+ ut_dbg_assertion_failed(0, __FILE__, (ulint) __LINE__); \
+ UT_DBG_PANIC; \
} while (0)
-#endif
#ifdef UNIV_DEBUG
#define ut_ad(EXPR) ut_a(EXPR)
diff --git a/innobase/include/ut0rnd.ic b/innobase/include/ut0rnd.ic
index 06d7012f60b..d2ab087d491 100644
--- a/innobase/include/ut0rnd.ic
+++ b/innobase/include/ut0rnd.ic
@@ -207,12 +207,12 @@ ut_fold_binary(
const byte* str, /* in: string of bytes */
ulint len) /* in: length */
{
- ulint i;
- ulint fold = 0;
+ const byte* str_end = str + len;
+ ulint fold = 0;
ut_ad(str);
- for (i = 0; i < len; i++) {
+ while (str < str_end) {
fold = ut_fold_ulint_pair(fold, (ulint)(*str));
str++;
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 73ecc717e0e..48db7ced0cb 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -292,7 +292,25 @@ waiting, in its lock queue. Solution: We can copy the locks as gap type
locks, so that also the waiting locks are transformed to granted gap type
locks on the inserted record. */
+/* LOCK COMPATIBILITY MATRIX
+ * IS IX S X AI
+ * IS + + + - +
+ * IX + + - - +
+ * S + - + - -
+ * X - - - - -
+ * AI + + - - -
+ *
+ * Note that for rows, InnoDB only acquires S or X locks.
+ * For tables, InnoDB normally acquires IS or IX locks.
+ * S or X table locks are only acquired for LOCK TABLES.
+ * Auto-increment (AI) locks are needed because of
+ * statement-level MySQL binlog.
+ * See also lock_mode_compatible().
+ */
+
+#ifdef UNIV_DEBUG
ibool lock_print_waits = FALSE;
+#endif /* UNIV_DEBUG */
/* The lock system */
lock_sys_t* lock_sys = NULL;
@@ -348,17 +366,26 @@ static
ibool
lock_deadlock_occurs(
/*=================*/
- /* out: TRUE if a deadlock was detected */
+ /* out: TRUE if a deadlock was detected and we
+ chose trx as a victim; FALSE if no deadlock, or
+ there was a deadlock, but we chose other
+ transaction(s) as victim(s) */
lock_t* lock, /* in: lock the transaction is requesting */
trx_t* trx); /* in: transaction */
/************************************************************************
Looks recursively for a deadlock. */
static
-ibool
+ulint
lock_deadlock_recursive(
/*====================*/
- /* out: TRUE if a deadlock was detected
- or the calculation took too long */
+ /* out: 0 if no deadlock found,
+ LOCK_VICTIM_IS_START if there was a deadlock
+ and we chose 'start' as the victim,
+ LOCK_VICTIM_IS_OTHER if a deadlock
+ was found and we chose some other trx as a
+ victim: we must do the search again in this
+ last case because there may be another
+ deadlock! */
trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
@@ -492,12 +519,7 @@ lock_clust_rec_cons_read_sees(
trx_id = row_get_rec_trx_id(rec, index, offsets);
- if (read_view_sees_trx_id(view, trx_id)) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(read_view_sees_trx_id(view, trx_id));
}
/*************************************************************************
@@ -1261,7 +1283,6 @@ lock_rec_get_next(
/*==============*/
/* out: next lock, NULL if none exists */
rec_t* rec, /* in: record on a page */
- ibool comp, /* in: TRUE=compact page format */
lock_t* lock) /* in: lock */
{
#ifdef UNIV_SYNC_DEBUG
@@ -1269,19 +1290,19 @@ lock_rec_get_next(
#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_type(lock) == LOCK_REC);
- for (;;) {
- lock = lock_rec_get_next_on_page(lock);
-
- if (lock == NULL) {
-
- return(NULL);
- }
-
- if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) {
-
- return(lock);
- }
+ if (page_rec_is_comp(rec)) {
+ do {
+ lock = lock_rec_get_next_on_page(lock);
+ } while (lock && !lock_rec_get_nth_bit(lock,
+ rec_get_heap_no(rec, TRUE)));
+ } else {
+ do {
+ lock = lock_rec_get_next_on_page(lock);
+ } while (lock && !lock_rec_get_nth_bit(lock,
+ rec_get_heap_no(rec, FALSE)));
}
+
+ return(lock);
}
/*************************************************************************
@@ -1294,22 +1315,18 @@ lock_rec_get_first(
rec_t* rec) /* in: record on a page */
{
lock_t* lock;
- ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first_on_page(rec);
- comp = page_is_comp(buf_frame_align(rec));
+ if (UNIV_LIKELY_NULL(lock)) {
+ ulint heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
- while (lock) {
- if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) {
-
- break;
+ while (lock && !lock_rec_get_nth_bit(lock, heap_no)) {
+ lock = lock_rec_get_next_on_page(lock);
}
-
- lock = lock_rec_get_next_on_page(lock);
}
return(lock);
@@ -1471,7 +1488,6 @@ lock_rec_has_expl(
for a supremum record we regard this always a gap
type request */
rec_t* rec, /* in: record */
- ibool comp, /* in: TRUE=compact page format */
trx_t* trx) /* in: transaction */
{
lock_t* lock;
@@ -1501,7 +1517,7 @@ lock_rec_has_expl(
return(lock);
}
- lock = lock_rec_get_next(rec, comp, lock);
+ lock = lock_rec_get_next(rec, lock);
}
return(NULL);
@@ -1520,7 +1536,6 @@ lock_rec_other_has_expl_req(
ulint wait, /* in: LOCK_WAIT if also waiting locks are
taken into account, or 0 if not */
rec_t* rec, /* in: record to look at */
- ibool comp, /* in: TRUE=compact record format */
trx_t* trx) /* in: transaction, or NULL if requests by all
transactions are taken into account */
{
@@ -1545,7 +1560,7 @@ lock_rec_other_has_expl_req(
return(lock);
}
- lock = lock_rec_get_next(rec, comp, lock);
+ lock = lock_rec_get_next(rec, lock);
}
return(NULL);
@@ -1566,13 +1581,11 @@ lock_rec_other_has_conflicting(
trx_t* trx) /* in: our transaction */
{
lock_t* lock;
- ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
- comp = page_is_comp(buf_frame_align(rec));
while (lock) {
if (lock_rec_has_to_wait(trx, mode, lock,
@@ -1581,7 +1594,7 @@ lock_rec_other_has_conflicting(
return(lock);
}
- lock = lock_rec_get_next(rec, comp, lock);
+ lock = lock_rec_get_next(rec, lock);
}
return(NULL);
@@ -1607,7 +1620,7 @@ lock_rec_find_similar_on_page(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec)));
+ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
lock = lock_rec_get_first_on_page(rec);
while (lock != NULL) {
@@ -1709,6 +1722,8 @@ lock_rec_create(
page_no = buf_frame_get_page_no(page);
heap_no = rec_get_heap_no(rec, page_is_comp(page));
+ ut_ad(!!page_is_comp(page) == index->table->comp);
+
/* If rec is the supremum record, then we reset the gap and
LOCK_REC_NOT_GAP bits, as all locks on the supremum are
automatically of the gap type */
@@ -1725,7 +1740,7 @@ lock_rec_create(
lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
- if (lock == NULL) {
+ if (UNIV_UNLIKELY(lock == NULL)) {
return(NULL);
}
@@ -1826,7 +1841,7 @@ lock_rec_enqueue_waiting(
lock_reset_lock_and_trx_wait(lock);
lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec,
- page_is_comp(buf_frame_align(rec))));
+ page_rec_is_comp(rec)));
return(DB_DEADLOCK);
}
@@ -1845,11 +1860,13 @@ lock_rec_enqueue_waiting(
ut_a(que_thr_stop(thr));
+#ifdef UNIV_DEBUG
if (lock_print_waits) {
fprintf(stderr, "Lock wait for trx %lu in index ",
(ulong) ut_dulint_get_low(trx->id));
ut_print_name(stderr, trx, index->name);
}
+#endif /* UNIV_DEBUG */
return(DB_LOCK_WAIT);
}
@@ -1876,7 +1893,6 @@ lock_rec_add_to_queue(
lock_t* lock;
lock_t* similar_lock = NULL;
ulint heap_no;
- page_t* page = buf_frame_align(rec);
ibool somebody_waits = FALSE;
#ifdef UNIV_SYNC_DEBUG
@@ -1885,11 +1901,11 @@ lock_rec_add_to_queue(
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, page_is_comp(page), trx));
+ rec, trx));
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_X)
|| !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
- rec, page_is_comp(page), trx));
+ rec, trx));
type_mode = type_mode | LOCK_REC;
@@ -1898,7 +1914,7 @@ lock_rec_add_to_queue(
try to avoid unnecessary memory consumption of a new record lock
struct for a gap type lock */
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
/* There should never be LOCK_REC_NOT_GAP on a supremum
@@ -1909,7 +1925,7 @@ lock_rec_add_to_queue(
/* Look for a waiting lock request on the same record or on a gap */
- heap_no = rec_get_heap_no(rec, page_is_comp(page));
+ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
lock = lock_rec_get_first_on_page(rec);
while (lock != NULL) {
@@ -1984,7 +2000,7 @@ lock_rec_lock_fast(
|| mode - (LOCK_MODE_MASK & mode) == 0
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
- heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec)));
+ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
lock = lock_rec_get_first_on_page(rec);
@@ -2065,8 +2081,7 @@ lock_rec_lock_slow(
trx = thr_get_trx(thr);
- if (lock_rec_has_expl(mode, rec,
- page_is_comp(buf_frame_align(rec)), trx)) {
+ if (lock_rec_has_expl(mode, rec, trx)) {
/* The trx already has a strong enough lock on rec: do
nothing */
@@ -2207,16 +2222,14 @@ lock_grant(
release it at the end of the SQL statement */
lock->trx->auto_inc_lock = lock;
- } else if (lock_get_type(lock) == LOCK_TABLE_EXP ||
- lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
- ut_a(lock_get_mode(lock) == LOCK_S
- || lock_get_mode(lock) == LOCK_X);
- }
+ }
+#ifdef UNIV_DEBUG
if (lock_print_waits) {
fprintf(stderr, "Lock wait for trx %lu ends\n",
(ulong) ut_dulint_get_low(lock->trx->id));
}
+#endif /* UNIV_DEBUG */
/* If we are resolving a deadlock by choosing another transaction
as a victim, then our original transaction may not be in the
@@ -2383,14 +2396,12 @@ lock_rec_reset_and_release_wait(
{
lock_t* lock;
ulint heap_no;
- ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- comp = page_is_comp(buf_frame_align(rec));
- heap_no = rec_get_heap_no(rec, comp);
+ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
lock = lock_rec_get_first(rec);
@@ -2401,7 +2412,7 @@ lock_rec_reset_and_release_wait(
lock_rec_reset_nth_bit(lock, heap_no);
}
- lock = lock_rec_get_next(rec, comp, lock);
+ lock = lock_rec_get_next(rec, lock);
}
}
@@ -2419,13 +2430,11 @@ lock_rec_inherit_to_gap(
the locks on this record */
{
lock_t* lock;
- ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
- comp = page_is_comp(buf_frame_align(rec));
while (lock != NULL) {
if (!lock_rec_get_insert_intention(lock)) {
@@ -2435,7 +2444,7 @@ lock_rec_inherit_to_gap(
heir, lock->index, lock->trx);
}
- lock = lock_rec_get_next(rec, comp, lock);
+ lock = lock_rec_get_next(rec, lock);
}
}
@@ -2452,13 +2461,11 @@ lock_rec_inherit_to_gap_if_gap_lock(
the locks on this record */
{
lock_t* lock;
- ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
- comp = page_is_comp(buf_frame_align(rec));
while (lock != NULL) {
if (!lock_rec_get_insert_intention(lock)
@@ -2470,7 +2477,7 @@ lock_rec_inherit_to_gap_if_gap_lock(
heir, lock->index, lock->trx);
}
- lock = lock_rec_get_next(rec, comp, lock);
+ lock = lock_rec_get_next(rec, lock);
}
}
@@ -2484,7 +2491,7 @@ lock_rec_move(
rec_t* receiver, /* in: record which gets locks; this record
must have no lock requests on it! */
rec_t* donator, /* in: record which gives locks */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
{
lock_t* lock;
ulint heap_no;
@@ -2514,7 +2521,7 @@ lock_rec_move(
lock_rec_add_to_queue(type_mode, receiver, lock->index,
lock->trx);
- lock = lock_rec_get_next(donator, comp, lock);
+ lock = lock_rec_get_next(donator, lock);
}
ut_ad(lock_rec_get_first(donator) == NULL);
@@ -2540,7 +2547,7 @@ lock_move_reorganize_page(
UT_LIST_BASE_NODE_T(lock_t) old_locks;
mem_heap_t* heap = NULL;
rec_t* sup;
- ibool comp;
+ ulint comp;
lock_mutex_enter_kernel();
@@ -2659,8 +2666,9 @@ lock_move_rec_list_end(
ulint heap_no;
rec_t* sup;
ulint type_mode;
- ibool comp;
-
+ ulint comp;
+ ut_ad(page == buf_frame_align(rec));
+
lock_mutex_enter_kernel();
/* Note: when we move locks from record to record, waiting locks
@@ -2745,7 +2753,7 @@ lock_move_rec_list_start(
page_cur_t cur2;
ulint heap_no;
ulint type_mode;
- ibool comp;
+ ulint comp;
ut_a(new_page);
@@ -2754,6 +2762,7 @@ lock_move_rec_list_start(
lock = lock_rec_get_first_on_page(page);
comp = page_is_comp(page);
ut_ad(comp == page_is_comp(new_page));
+ ut_ad(page == buf_frame_align(rec));
while (lock != NULL) {
@@ -2812,7 +2821,7 @@ lock_update_split_right(
page_t* right_page, /* in: right page */
page_t* left_page) /* in: left page */
{
- ibool comp;
+ ulint comp;
lock_mutex_enter_kernel();
comp = page_is_comp(left_page);
ut_ad(comp == page_is_comp(right_page));
@@ -2875,7 +2884,7 @@ lock_update_root_raise(
page_t* new_page, /* in: index page to which copied */
page_t* root) /* in: root page */
{
- ibool comp;
+ ulint comp;
lock_mutex_enter_kernel();
comp = page_is_comp(root);
ut_ad(comp == page_is_comp(new_page));
@@ -2898,7 +2907,7 @@ lock_update_copy_and_discard(
page_t* new_page, /* in: index page to which copied */
page_t* page) /* in: index page; NOT the root! */
{
- ibool comp;
+ ulint comp;
lock_mutex_enter_kernel();
comp = page_is_comp(page);
ut_ad(comp == page_is_comp(new_page));
@@ -2945,31 +2954,34 @@ lock_update_merge_left(
page_t* right_page) /* in: merged index page which will be
discarded */
{
- ibool comp;
+ rec_t* left_next_rec;
+ rec_t* left_supremum;
+ ulint comp;
lock_mutex_enter_kernel();
comp = page_is_comp(left_page);
ut_ad(comp == page_is_comp(right_page));
+ ut_ad(left_page == buf_frame_align(orig_pred));
- if (page_rec_get_next(orig_pred) != page_get_supremum_rec(left_page)) {
+ left_next_rec = page_rec_get_next(orig_pred);
+ left_supremum = page_get_supremum_rec(left_page);
+
+ if (UNIV_LIKELY(left_next_rec != left_supremum)) {
/* Inherit the locks on the supremum of the left page to the
first record which was moved from the right page */
- lock_rec_inherit_to_gap(page_rec_get_next(orig_pred),
- page_get_supremum_rec(left_page));
+ lock_rec_inherit_to_gap(left_next_rec, left_supremum);
/* Reset the locks on the supremum of the left page,
releasing waiting transactions */
- lock_rec_reset_and_release_wait(page_get_supremum_rec(
- left_page));
+ lock_rec_reset_and_release_wait(left_supremum);
}
/* Move the locks from the supremum of right page to the supremum
of the left page */
- lock_rec_move(page_get_supremum_rec(left_page),
- page_get_supremum_rec(right_page), comp);
+ lock_rec_move(left_supremum, page_get_supremum_rec(right_page), comp);
lock_rec_free_all_from_discard_page(right_page);
@@ -3028,7 +3040,7 @@ lock_update_discard(
lock_rec_reset_and_release_wait(rec);
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
break;
}
@@ -3091,19 +3103,16 @@ actual record is being moved. */
void
lock_rec_store_on_page_infimum(
/*===========================*/
+ page_t* page, /* in: page containing the record */
rec_t* rec) /* in: record whose lock state is stored
on the infimum record of the same page; lock
bits are reset on the record */
{
- page_t* page;
- ibool comp;
-
- page = buf_frame_align(rec);
- comp = page_is_comp(page);
+ ut_ad(page == buf_frame_align(rec));
lock_mutex_enter_kernel();
- lock_rec_move(page_get_infimum_rec(page), rec, comp);
+ lock_rec_move(page_get_infimum_rec(page), rec, page_is_comp(page));
lock_mutex_exit_kernel();
}
@@ -3120,10 +3129,10 @@ lock_rec_restore_from_page_infimum(
whose infimum stored the lock state; lock bits are
reset on the infimum */
{
- ibool comp;
+ ulint comp;
lock_mutex_enter_kernel();
comp = page_is_comp(page);
- ut_ad(comp == page_is_comp(buf_frame_align(rec)));
+ ut_ad(!comp == !page_rec_is_comp(rec));
lock_rec_move(rec, page_get_infimum_rec(page), comp);
@@ -3316,11 +3325,11 @@ lock_deadlock_recursive(
} else {
lock_table_print(ef, start->wait_lock);
}
-
+#ifdef UNIV_DEBUG
if (lock_print_waits) {
fputs("Deadlock detected\n", stderr);
}
-
+#endif /* UNIV_DEBUG */
if (ut_dulint_cmp(wait_lock->trx->undo_no,
start->undo_no) >= 0) {
/* Our recursion starting point
@@ -3418,14 +3427,6 @@ lock_table_create(
lock->type_mode = type_mode | LOCK_TABLE;
lock->trx = trx;
- if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- lock->trx->n_lock_table_exp++;
- }
-
- if (lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
- lock->trx->n_lock_table_transactional++;
- }
-
lock->un_member.tab_lock.table = table;
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
@@ -3462,14 +3463,6 @@ lock_table_remove_low(
trx->auto_inc_lock = NULL;
}
- if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- trx->n_lock_table_exp--;
- }
-
- if (lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
- trx->n_lock_table_transactional--;
- }
-
UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock);
UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock);
}
@@ -3600,10 +3593,7 @@ lock_table(
/* out: DB_SUCCESS, DB_LOCK_WAIT,
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
- does nothing;
- if LOCK_TABLE_EXP|LOCK_TABLE_TRANSACTIONAL
- bits are set,
- creates an explicit table lock */
+ does nothing */
dict_table_t* table, /* in: database table in dictionary cache */
ulint mode, /* in: lock mode */
que_thr_t* thr) /* in: query thread */
@@ -3618,8 +3608,7 @@ lock_table(
return(DB_SUCCESS);
}
- ut_a(flags == 0 || flags == LOCK_TABLE_EXP ||
- flags == LOCK_TABLE_TRANSACTIONAL);
+ ut_a(flags == 0);
trx = thr_get_trx(thr);
@@ -3732,9 +3721,7 @@ lock_table_dequeue(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(lock_get_type(in_lock) == LOCK_TABLE ||
- lock_get_type(in_lock) == LOCK_TABLE_EXP ||
- lock_get_type(in_lock) == LOCK_TABLE_TRANSACTIONAL);
+ ut_a(lock_get_type(in_lock) == LOCK_TABLE);
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
@@ -3838,12 +3825,6 @@ lock_release_off_kernel(
}
lock_table_dequeue(lock);
-
- if (lock_get_type(lock) == LOCK_TABLE_EXP ||
- lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
- ut_a(lock_get_mode(lock) == LOCK_S
- || lock_get_mode(lock) == LOCK_X);
- }
}
if (count == LOCK_RELEASE_KERNEL_INTERVAL) {
@@ -3863,74 +3844,6 @@ lock_release_off_kernel(
mem_heap_empty(trx->lock_heap);
ut_a(trx->auto_inc_lock == NULL);
- ut_a(trx->n_lock_table_exp == 0);
- ut_a(trx->n_lock_table_transactional == 0);
-}
-
-/*************************************************************************
-Releases table locks explicitly requested with LOCK TABLES (indicated by
-lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
-because of these locks. */
-
-void
-lock_release_tables_off_kernel(
-/*===========================*/
- trx_t* trx) /* in: transaction */
-{
- dict_table_t* table;
- 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);
-
- count = 0;
-
- while (lock != NULL) {
-
- count++;
-
- if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_a(lock_get_mode(lock) == LOCK_S
- || lock_get_mode(lock) == LOCK_X);
- if (trx->insert_undo || trx->update_undo) {
-
- /* The trx may have modified the table.
- We block the use of the MySQL query
- cache for all currently active
- transactions. */
-
- table = lock->un_member.tab_lock.table;
-
- table->query_cache_inv_trx_id =
- trx_sys->max_trx_id;
- }
-
- lock_table_dequeue(lock);
-
- lock = UT_LIST_GET_LAST(trx->trx_locks);
- continue;
- }
-
- if (count == LOCK_RELEASE_KERNEL_INTERVAL) {
- /* Release the kernel mutex for a while, so that we
- do not monopolize it */
-
- lock_mutex_exit_kernel();
-
- lock_mutex_enter_kernel();
-
- count = 0;
- }
-
- lock = UT_LIST_GET_PREV(trx_locks, lock);
- }
-
- ut_a(trx->n_lock_table_exp == 0);
- ut_a(trx->n_lock_table_transactional == 0);
}
/*************************************************************************
@@ -4043,15 +3956,7 @@ lock_table_print(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(lock_get_type(lock) == LOCK_TABLE ||
- lock_get_type(lock) == LOCK_TABLE_EXP ||
- lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL);
-
- if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- fputs("EXPLICIT ", file);
- } else if (lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
- fputs("TRANSACTIONAL ", file);
- }
+ ut_a(lock_get_type(lock) == LOCK_TABLE);
fputs("TABLE LOCK table ", file);
ut_print_name(file, lock->trx, lock->un_member.tab_lock.table->name);
@@ -4187,7 +4092,7 @@ lock_rec_print(
}
mtr_commit(&mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -4483,15 +4388,14 @@ lock_rec_queue_validate(
{
trx_t* impl_trx;
lock_t* lock;
- ibool comp;
ut_a(rec);
ut_ad(rec_offs_validate(rec, index, offsets));
- comp = page_is_comp(buf_frame_align(rec));
+ ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
lock_mutex_enter_kernel();
- if (page_rec_is_supremum(rec) || page_rec_is_infimum(rec)) {
+ if (!page_rec_is_user_rec(rec)) {
lock = lock_rec_get_first(rec);
@@ -4511,7 +4415,7 @@ lock_rec_queue_validate(
ut_a(lock->index == index);
}
- lock = lock_rec_get_next(rec, comp, lock);
+ lock = lock_rec_get_next(rec, lock);
}
lock_mutex_exit_kernel();
@@ -4524,10 +4428,10 @@ lock_rec_queue_validate(
impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
- LOCK_WAIT, rec, comp, impl_trx)) {
+ LOCK_WAIT, rec, impl_trx)) {
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
- comp, impl_trx));
+ impl_trx));
}
}
@@ -4541,10 +4445,10 @@ lock_rec_queue_validate(
rec, index, offsets);
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
- LOCK_WAIT, rec, comp, impl_trx)) {
+ LOCK_WAIT, rec, impl_trx)) {
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
- rec, comp, impl_trx));
+ rec, impl_trx));
}
}
@@ -4561,21 +4465,23 @@ lock_rec_queue_validate(
}
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
+
+ ulint mode;
if (lock_get_mode(lock) == LOCK_S) {
- ut_a(!lock_rec_other_has_expl_req(LOCK_X,
- 0, 0, rec, comp, lock->trx));
+ mode = LOCK_X;
} else {
- ut_a(!lock_rec_other_has_expl_req(LOCK_S,
- 0, 0, rec, comp, lock->trx));
+ mode = LOCK_S;
}
+ ut_a(!lock_rec_other_has_expl_req(mode,
+ 0, 0, rec, lock->trx));
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
ut_a(lock_rec_has_to_wait_in_queue(lock));
}
- lock = lock_rec_get_next(rec, comp, lock);
+ lock = lock_rec_get_next(rec, lock);
}
lock_mutex_exit_kernel();
@@ -4673,7 +4579,7 @@ function_exit:
mtr_commit(&mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(TRUE);
@@ -4859,7 +4765,7 @@ lock_rec_insert_check_and_lock(
offsets = rec_get_offsets(next_rec, index, offsets_,
ULINT_UNDEFINED, &heap);
ut_ad(lock_rec_queue_validate(next_rec, index, offsets));
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -4887,7 +4793,7 @@ lock_rec_convert_impl_to_expl(
#endif /* UNIV_SYNC_DEBUG */
ut_ad(page_rec_is_user_rec(rec));
ut_ad(rec_offs_validate(rec, index, offsets));
- ut_ad(page_is_comp(buf_frame_align(rec)) == index->table->comp);
+ ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
if (index->type & DICT_CLUSTERED) {
impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
@@ -4901,7 +4807,7 @@ lock_rec_convert_impl_to_expl(
record, set one for it */
if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
- index->table->comp, impl_trx)) {
+ impl_trx)) {
lock_rec_add_to_queue(LOCK_REC | LOCK_X
| LOCK_REC_NOT_GAP, rec, index,
@@ -5008,7 +4914,7 @@ lock_sec_rec_modify_check_and_lock(
offsets = rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap);
ut_ad(lock_rec_queue_validate(rec, index, offsets));
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index 560f51401ac..2f76bf450db 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -57,10 +57,11 @@ ulint log_fsp_current_free_limit = 0;
/* Global log system variable */
log_t* log_sys = NULL;
+#ifdef UNIV_DEBUG
ibool log_do_write = TRUE;
ibool log_debug_writes = FALSE;
-
+#endif /* UNIV_DEBUG */
/* These control how often we print warnings if the last checkpoint is too
old */
@@ -974,22 +975,24 @@ log_group_check_flush_completion(
#endif /* UNIV_SYNC_DEBUG */
if (!log_sys->one_flushed && group->n_pending_writes == 0) {
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Log flushed first to group %lu\n", (ulong) group->id);
}
-
+#endif /* UNIV_DEBUG */
log_sys->written_to_some_lsn = log_sys->write_lsn;
log_sys->one_flushed = TRUE;
return(LOG_UNLOCK_NONE_FLUSHED_LOCK);
}
+#ifdef UNIV_DEBUG
if (log_debug_writes && (group->n_pending_writes == 0)) {
fprintf(stderr, "Log flushed to group %lu\n", (ulong) group->id);
}
-
+#endif /* UNIV_DEBUG */
return(0);
}
@@ -1066,12 +1069,13 @@ log_io_complete(
fil_flush(group->space_id);
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Checkpoint info written to group %lu\n",
group->id);
}
-
+#endif /* UNIV_DEBUG */
log_io_complete_checkpoint();
return;
@@ -1133,12 +1137,13 @@ log_group_file_header_flush(
dest_offset = nth_file * group->file_size;
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Writing log file header to group %lu file %lu\n",
(ulong) group->id, (ulong) nth_file);
}
-
+#endif /* UNIV_DEBUG */
if (log_do_write) {
log_sys->n_log_ios++;
@@ -1226,7 +1231,8 @@ loop:
} else {
write_len = len;
}
-
+
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
@@ -1250,7 +1256,7 @@ loop:
+ i * OS_FILE_LOG_BLOCK_SIZE));
}
}
-
+#endif /* UNIV_DEBUG */
/* Calculate the checksums for each log block and write them to
the trailer fields of the log blocks */
@@ -1384,6 +1390,7 @@ loop:
return;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Writing log from %lu %lu up to lsn %lu %lu\n",
@@ -1392,7 +1399,7 @@ loop:
(ulong) ut_dulint_get_high(log_sys->lsn),
(ulong) ut_dulint_get_low(log_sys->lsn));
}
-
+#endif /* UNIV_DEBUG */
log_sys->n_pending_writes++;
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -1961,12 +1968,14 @@ log_checkpoint(
log_sys->next_checkpoint_lsn = oldest_lsn;
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr, "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_DEBUG */
log_groups_write_checkpoint_info();
@@ -2029,8 +2038,6 @@ log_checkpoint_margin(void)
ulint checkpoint_age;
ulint advance;
dulint oldest_lsn;
- dulint new_oldest;
- ibool do_preflush;
ibool sync;
ibool checkpoint_sync;
ibool do_checkpoint;
@@ -2038,7 +2045,6 @@ log_checkpoint_margin(void)
loop:
sync = FALSE;
checkpoint_sync = FALSE;
- do_preflush = FALSE;
do_checkpoint = FALSE;
mutex_enter(&(log->mutex));
@@ -2058,21 +2064,13 @@ loop:
/* A flush is urgent: we have to do a synchronous preflush */
sync = TRUE;
-
advance = 2 * (age - log->max_modified_age_sync);
-
- new_oldest = ut_dulint_add(oldest_lsn, advance);
-
- do_preflush = TRUE;
-
} else if (age > log->max_modified_age_async) {
/* A flush is not urgent: we do an asynchronous preflush */
advance = age - log->max_modified_age_async;
-
- new_oldest = ut_dulint_add(oldest_lsn, advance);
-
- do_preflush = TRUE;
+ } else {
+ advance = 0;
}
checkpoint_age = ut_dulint_minus(log->lsn, log->last_checkpoint_lsn);
@@ -2096,7 +2094,9 @@ loop:
mutex_exit(&(log->mutex));
- if (do_preflush) {
+ if (advance) {
+ dulint new_oldest = ut_dulint_add(oldest_lsn, advance);
+
success = log_preflush_pool_modified_pages(new_oldest, sync);
/* If the flush succeeded, this thread has done its part
@@ -2347,9 +2347,11 @@ loop:
exit(1);
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr, "Created archive file %s\n", name);
}
+#endif /* UNIV_DEBUG */
ret = os_file_close(file_handle);
@@ -2375,7 +2377,8 @@ loop:
len = group->file_size - (next_offset % group->file_size);
}
-
+
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Archiving starting at lsn %lu %lu, len %lu to group %lu\n",
@@ -2383,6 +2386,7 @@ loop:
(ulong) ut_dulint_get_low(start_lsn),
(ulong) len, (ulong) group->id);
}
+#endif /* UNIV_DEBUG */
log_sys->n_pending_archive_ios++;
@@ -2473,11 +2477,13 @@ log_archive_write_complete_groups(void)
trunc_files = n_files - 1;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes && trunc_files) {
fprintf(stderr,
"Complete file(s) archived to group %lu\n",
(ulong) group->id);
}
+#endif /* UNIV_DEBUG */
/* Calculate the archive file space start lsn */
start_lsn = ut_dulint_subtract(log_sys->next_archived_lsn,
@@ -2500,9 +2506,11 @@ log_archive_write_complete_groups(void)
fil_space_truncate_start(group->archive_space_id,
trunc_files * group->file_size);
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fputs("Archiving writes completed\n", stderr);
}
+#endif /* UNIV_DEBUG */
}
/**********************************************************
@@ -2519,9 +2527,11 @@ log_archive_check_completion_low(void)
if (log_sys->n_pending_archive_ios == 0
&& log_sys->archiving_phase == LOG_ARCHIVE_READ) {
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fputs("Archiving read completed\n", stderr);
}
+#endif /* UNIV_DEBUG */
/* Archive buffer has now been read in: start archive writes */
@@ -2665,6 +2675,7 @@ loop:
log_sys->next_archived_lsn = limit_lsn;
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Archiving from lsn %lu %lu to lsn %lu %lu\n",
@@ -2673,6 +2684,7 @@ loop:
(ulong) ut_dulint_get_high(limit_lsn),
(ulong) ut_dulint_get_low(limit_lsn));
}
+#endif /* UNIV_DEBUG */
/* Read the log segment to the archive buffer */
@@ -2775,12 +2787,14 @@ log_archive_close_groups(
group->archived_file_no += 2;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Incrementing arch file no to %lu in log group %lu\n",
(ulong) group->archived_file_no + 2,
(ulong) group->id);
}
+#endif /* UNIV_DEBUG */
}
}
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index 6597122f104..42e854398ba 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -477,6 +477,7 @@ recv_find_max_checkpoint(
max_no = ut_dulint_zero;
*max_group = NULL;
+ *max_field = 0;
buf = log_sys->checkpoint_buf;
@@ -489,6 +490,7 @@ recv_find_max_checkpoint(
log_group_read_checkpoint_info(group, field);
if (!recv_check_cp_is_consistent(buf)) {
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n",
@@ -498,7 +500,7 @@ recv_find_max_checkpoint(
+ LOG_CHECKPOINT_CHECKSUM_1));
}
-
+#endif /* UNIV_DEBUG */
goto not_consistent;
}
@@ -511,13 +513,15 @@ recv_find_max_checkpoint(
checkpoint_no =
mach_read_from_8(buf + LOG_CHECKPOINT_NO);
+#ifdef UNIV_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_DEBUG */
+
if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) {
*max_group = group;
*max_field = field;
@@ -540,7 +544,6 @@ recv_find_max_checkpoint(
"InnoDB: to create the InnoDB data files, but log file creation failed.\n"
"InnoDB: If that is the case, please refer to\n"
"InnoDB: http://dev.mysql.com/doc/mysql/en/Error_creating_InnoDB.html\n");
-
return(DB_ERROR);
}
@@ -765,6 +768,8 @@ recv_parse_or_apply_log_rec_body(
case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_REC_INSERT, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr,
index, page, mtr);
}
@@ -772,20 +777,29 @@ recv_parse_or_apply_log_rec_body(
case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
ptr = btr_cur_parse_del_mark_set_clust_rec(ptr,
end_ptr, index, page);
}
break;
- case MLOG_REC_SEC_DELETE_MARK: case MLOG_COMP_REC_SEC_DELETE_MARK:
- if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
- type == MLOG_COMP_REC_SEC_DELETE_MARK, &index))) {
- ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr,
- index, page);
+ case MLOG_COMP_REC_SEC_DELETE_MARK:
+ /* This log record type is obsolete, but we process it for
+ backward compatibility with MySQL 5.0.3 and 5.0.4. */
+ ut_a(!page || page_is_comp(page));
+ ptr = mlog_parse_index(ptr, end_ptr, TRUE, &index);
+ if (!ptr) {
+ break;
}
+ /* Fall through */
+ case MLOG_REC_SEC_DELETE_MARK:
+ ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr, page);
break;
case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
ptr = btr_cur_parse_update_in_place(ptr, end_ptr,
page, index);
}
@@ -795,6 +809,8 @@ recv_parse_or_apply_log_rec_body(
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_LIST_END_DELETE
|| type == MLOG_COMP_LIST_START_DELETE, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
ptr = page_parse_delete_rec_list(type, ptr, end_ptr,
index, page, mtr);
}
@@ -802,6 +818,8 @@ recv_parse_or_apply_log_rec_body(
case MLOG_LIST_END_COPY_CREATED: case MLOG_COMP_LIST_END_COPY_CREATED:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
ptr = page_parse_copy_rec_list_to_created_page(ptr,
end_ptr, index, page, mtr);
}
@@ -809,6 +827,8 @@ recv_parse_or_apply_log_rec_body(
case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_PAGE_REORGANIZE, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
ptr = btr_parse_page_reorganize(ptr, end_ptr, index,
page, mtr);
}
@@ -841,6 +861,8 @@ recv_parse_or_apply_log_rec_body(
case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
type == MLOG_COMP_REC_DELETE, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
ptr = page_cur_parse_delete_rec(ptr, end_ptr,
index, page, mtr);
}
@@ -1153,6 +1175,7 @@ recv_recover_page(
}
modification_to_page = FALSE;
+ start_lsn = end_lsn = ut_dulint_zero;
recv = UT_LIST_GET_FIRST(recv_addr->rec_list);
@@ -1186,6 +1209,7 @@ recv_recover_page(
start_lsn = recv->start_lsn;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Applying log rec type %lu len %lu to space %lu page no %lu\n",
@@ -1193,6 +1217,7 @@ recv_recover_page(
(ulong) recv_addr->space,
(ulong) recv_addr->page_no);
}
+#endif /* UNIV_DEBUG */
recv_parse_or_apply_log_rec_body(recv->type, buf,
buf + recv->len, page, &mtr);
@@ -1779,6 +1804,8 @@ recv_parse_log_rec(
{
byte* new_ptr;
+ *body = NULL;
+
if (ptr == end_ptr) {
return(0);
@@ -1801,25 +1828,25 @@ recv_parse_log_rec(
new_ptr = mlog_parse_initial_log_record(ptr, end_ptr, type, space,
page_no);
- if (!new_ptr) {
+ *body = new_ptr;
+
+ if (UNIV_UNLIKELY(!new_ptr)) {
return(0);
}
/* Check that page_no is sensible */
- if (*page_no > 0x8FFFFFFFUL) {
+ if (UNIV_UNLIKELY(*page_no > 0x8FFFFFFFUL)) {
recv_sys->found_corrupt_log = TRUE;
return(0);
}
- *body = new_ptr;
-
new_ptr = recv_parse_or_apply_log_rec_body(*type, new_ptr, end_ptr,
NULL, NULL);
- if (new_ptr == NULL) {
+ if (UNIV_UNLIKELY(new_ptr == NULL)) {
return(0);
}
@@ -2013,12 +2040,14 @@ loop:
recv_sys->recovered_offset += len;
recv_sys->recovered_lsn = new_recovered_lsn;
+#ifdef UNIV_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_DEBUG */
if (type == MLOG_DUMMY_RECORD) {
/* Do nothing */
@@ -2101,13 +2130,15 @@ loop:
body, ptr + len);
#endif /* UNIV_LOG_REPLICATE */
}
-
+
+#ifdef UNIV_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_DEBUG */
total_len += len;
n_recs++;
@@ -2514,6 +2545,7 @@ recv_group_scan_log_recs(
start_lsn = end_lsn;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Scanned group %lu up to log sequence number %lu %lu\n",
@@ -2521,6 +2553,7 @@ recv_group_scan_log_recs(
(ulong) ut_dulint_get_high(*group_scanned_lsn),
(ulong) ut_dulint_get_low(*group_scanned_lsn));
}
+#endif /* UNIV_DEBUG */
}
/************************************************************
@@ -2906,10 +2939,12 @@ recv_recovery_from_checkpoint_finish(void)
recv_apply_hashed_log_recs(TRUE);
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Log records applied to the database\n");
}
+#endif /* UNIV_DEBUG */
if (recv_needed_recovery) {
trx_sys_print_mysql_master_log_pos();
@@ -3246,6 +3281,7 @@ ask_again:
break;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Archive read starting at lsn %lu %lu, len %lu from file %s\n",
@@ -3253,6 +3289,7 @@ ask_again:
(ulong) ut_dulint_get_low(start_lsn),
(ulong) len, name);
}
+#endif /* UNIV_DEBUG */
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE,
group->archive_space_id, read_offset / UNIV_PAGE_SIZE,
diff --git a/innobase/mtr/mtr0log.c b/innobase/mtr/mtr0log.c
index 4f826f242e8..0308619073a 100644
--- a/innobase/mtr/mtr0log.c
+++ b/innobase/mtr/mtr0log.c
@@ -15,6 +15,7 @@ Created 12/7/1995 Heikki Tuuri
#include "buf0buf.h"
#include "dict0boot.h"
#include "log0recv.h"
+#include "page0page.h"
/************************************************************
Catenates n bytes to the mtr log. */
@@ -22,9 +23,9 @@ Catenates n bytes to the mtr log. */
void
mlog_catenate_string(
/*=================*/
- mtr_t* mtr, /* in: mtr */
- byte* str, /* in: string to write */
- ulint len) /* in: string length */
+ mtr_t* mtr, /* in: mtr */
+ const byte* str, /* in: string to write */
+ ulint len) /* in: string length */
{
dyn_array_t* mlog;
@@ -301,14 +302,15 @@ corresponding log record to the mini-transaction log. */
void
mlog_write_string(
/*==============*/
- byte* ptr, /* in: pointer where to write */
- byte* str, /* in: string to write */
- ulint len, /* in: string length */
- mtr_t* mtr) /* in: mini-transaction handle */
+ byte* ptr, /* in: pointer where to write */
+ const byte* str, /* in: string to write */
+ ulint len, /* in: string length */
+ mtr_t* mtr) /* in: mini-transaction handle */
{
byte* log_ptr;
- if (ptr < buf_pool->frame_zero || ptr >= buf_pool->high_end) {
+ if (UNIV_UNLIKELY(ptr < buf_pool->frame_zero)
+ || UNIV_UNLIKELY(ptr >= buf_pool->high_end)) {
fprintf(stderr,
"InnoDB: Error: trying to write to a stray memory location %p\n", ptr);
ut_error;
@@ -405,7 +407,9 @@ mlog_open_and_write_index(
const byte* log_start;
const byte* log_end;
- if (!index->table->comp) {
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
+
+ if (!page_rec_is_comp(rec)) {
log_start = log_ptr = mlog_open(mtr, 11 + size);
if (!log_ptr) {
return(NULL); /* logging is disabled */
@@ -498,6 +502,8 @@ mlog_parse_index(
dict_table_t* table;
dict_index_t* ind;
+ ut_ad(comp == FALSE || comp == TRUE);
+
if (comp) {
if (end_ptr < ptr + 4) {
return(NULL);
diff --git a/innobase/mtr/mtr0mtr.c b/innobase/mtr/mtr0mtr.c
index 6e918806eb1..da045be1f62 100644
--- a/innobase/mtr/mtr0mtr.c
+++ b/innobase/mtr/mtr0mtr.c
@@ -48,16 +48,11 @@ mtr_memo_slot_release(
object = slot->object;
type = slot->type;
- if (object != NULL) {
+ if (UNIV_LIKELY(object != NULL)) {
if (type <= MTR_MEMO_BUF_FIX) {
buf_page_release((buf_block_t*)object, type, mtr);
} else if (type == MTR_MEMO_S_LOCK) {
rw_lock_s_unlock((rw_lock_t*)object);
-#ifndef UNIV_DEBUG
- } else {
- rw_lock_x_unlock((rw_lock_t*)object);
- }
-#endif
#ifdef UNIV_DEBUG
} else if (type == MTR_MEMO_X_LOCK) {
rw_lock_x_unlock((rw_lock_t*)object);
@@ -65,8 +60,11 @@ mtr_memo_slot_release(
ut_ad(type == MTR_MEMO_MODIFY);
ut_ad(mtr_memo_contains(mtr, object,
MTR_MEMO_PAGE_X_FIX));
- }
+#else
+ } else {
+ rw_lock_x_unlock((rw_lock_t*)object);
#endif
+ }
}
slot->object = NULL;
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index ac5d1c72c72..48dc808e36c 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -83,7 +83,7 @@ struct os_aio_slot_struct{
made and only the slot message
needs to be passed to the caller
of os_aio_simulated_handle */
- void* message1; /* message which is given by the */
+ fil_node_t* message1; /* message which is given by the */
void* message2; /* the requester of an aio operation
and which can be used to identify
which pending aio operation was
@@ -133,17 +133,17 @@ os_event_t* os_aio_segment_wait_events = NULL;
/* The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These
are NULL when the module has not yet been initialized. */
-os_aio_array_t* os_aio_read_array = NULL;
-os_aio_array_t* os_aio_write_array = NULL;
-os_aio_array_t* os_aio_ibuf_array = NULL;
-os_aio_array_t* os_aio_log_array = NULL;
-os_aio_array_t* os_aio_sync_array = NULL;
+static os_aio_array_t* os_aio_read_array = NULL;
+static os_aio_array_t* os_aio_write_array = NULL;
+static os_aio_array_t* os_aio_ibuf_array = NULL;
+static os_aio_array_t* os_aio_log_array = NULL;
+static os_aio_array_t* os_aio_sync_array = NULL;
-ulint os_aio_n_segments = ULINT_UNDEFINED;
+static ulint os_aio_n_segments = ULINT_UNDEFINED;
/* If the following is TRUE, read i/o handler threads try to
wait until a batch of new read requests have been posted */
-ibool os_aio_recommend_sleep_for_read_threads = FALSE;
+static ibool os_aio_recommend_sleep_for_read_threads = FALSE;
ulint os_n_file_reads = 0;
ulint os_bytes_read_since_printout = 0;
@@ -158,7 +158,7 @@ ibool os_has_said_disk_full = FALSE;
/* The mutex protecting the following counts of pending pread and pwrite
operations */
-os_mutex_t os_file_count_mutex;
+static os_mutex_t os_file_count_mutex;
ulint os_file_n_pending_preads = 0;
ulint os_file_n_pending_pwrites = 0;
@@ -1653,7 +1653,7 @@ os_file_get_size_as_iblonglong(
}
/***************************************************************************
-Sets a file size. This function can be used to extend or truncate a file. */
+Write the specified number of zeros to a newly created file. */
ibool
os_file_set_size(
@@ -1666,47 +1666,46 @@ os_file_set_size(
size */
ulint size_high)/* in: most significant 32 bits of size */
{
- ib_longlong offset;
- ib_longlong low;
- ulint n_bytes;
+ ib_longlong current_size;
+ ib_longlong desired_size;
ibool ret;
byte* buf;
byte* buf2;
- ulint i;
+ ulint buf_size;
ut_a(size == (size & 0xFFFFFFFF));
- /* We use a very big 8 MB buffer in writing because Linux may be
- extremely slow in fsync on 1 MB writes */
+ current_size = 0;
+ desired_size = (ib_longlong)size + (((ib_longlong)size_high) << 32);
- buf2 = ut_malloc(UNIV_PAGE_SIZE * 513);
+ /* Write up to 1 megabyte at a time. */
+ buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE))
+ * UNIV_PAGE_SIZE;
+ buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE);
/* Align the buffer for possible raw i/o */
buf = ut_align(buf2, UNIV_PAGE_SIZE);
/* Write buffer full of zeros */
- for (i = 0; i < UNIV_PAGE_SIZE * 512; i++) {
- buf[i] = '\0';
- }
-
- offset = 0;
- low = (ib_longlong)size + (((ib_longlong)size_high) << 32);
+ memset(buf, 0, buf_size);
- if (low >= (ib_longlong)(100 * 1024 * 1024)) {
+ if (desired_size >= (ib_longlong)(100 * 1024 * 1024)) {
fprintf(stderr, "InnoDB: Progress in MB:");
}
- while (offset < low) {
- if (low - offset < UNIV_PAGE_SIZE * 512) {
- n_bytes = (ulint)(low - offset);
- } else {
- n_bytes = UNIV_PAGE_SIZE * 512;
- }
-
+ while (current_size < desired_size) {
+ ulint n_bytes;
+
+ if (desired_size - current_size < (ib_longlong) buf_size) {
+ n_bytes = (ulint) (desired_size - current_size);
+ } else {
+ n_bytes = buf_size;
+ }
+
ret = os_file_write(name, file, buf,
- (ulint)(offset & 0xFFFFFFFF),
- (ulint)(offset >> 32),
+ (ulint)(current_size & 0xFFFFFFFF),
+ (ulint)(current_size >> 32),
n_bytes);
if (!ret) {
ut_free(buf2);
@@ -1714,18 +1713,18 @@ os_file_set_size(
}
/* Print about progress for each 100 MB written */
- if ((ib_longlong) (offset + n_bytes) / (ib_longlong)(100 * 1024 * 1024)
- != offset / (ib_longlong)(100 * 1024 * 1024)) {
+ if ((current_size + n_bytes) / (ib_longlong)(100 * 1024 * 1024)
+ != current_size / (ib_longlong)(100 * 1024 * 1024)) {
fprintf(stderr, " %lu00",
- (ulong) ((offset + n_bytes)
+ (ulong) ((current_size + n_bytes)
/ (ib_longlong)(100 * 1024 * 1024)));
}
- offset += n_bytes;
+ current_size += n_bytes;
}
- if (low >= (ib_longlong)(100 * 1024 * 1024)) {
+ if (desired_size >= (ib_longlong)(100 * 1024 * 1024)) {
fprintf(stderr, "\n");
}
@@ -3025,7 +3024,7 @@ os_aio_array_reserve_slot(
/* out: pointer to slot */
ulint type, /* in: OS_FILE_READ or OS_FILE_WRITE */
os_aio_array_t* array, /* in: aio array */
- void* message1,/* in: message to be passed along with
+ fil_node_t* message1,/* in: message to be passed along with
the aio operation */
void* message2,/* in: message to be passed along with
the aio operation */
@@ -3287,7 +3286,7 @@ os_aio(
ulint offset_high, /* in: most significant 32 bits of
offset */
ulint n, /* in: number of bytes to read or write */
- void* message1,/* in: messages for the aio handler (these
+ fil_node_t* message1,/* in: messages for the aio handler (these
can be used to identify a completed aio
operation); if mode is OS_AIO_SYNC, these
are ignored */
@@ -3299,7 +3298,7 @@ os_aio(
ibool retval;
BOOL ret = TRUE;
DWORD len = (DWORD) n;
- void* dummy_mess1;
+ struct fil_node_struct * dummy_mess1;
void* dummy_mess2;
ulint dummy_type;
#endif
@@ -3472,7 +3471,7 @@ os_aio_windows_handle(
ignored */
ulint pos, /* this parameter is used only in sync aio:
wait for the aio slot at this position */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -3563,7 +3562,7 @@ os_aio_posix_handle(
/*================*/
/* out: TRUE if the aio operation succeeded */
ulint array_no, /* in: array number 0 - 3 */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -3644,7 +3643,7 @@ os_aio_simulated_handle(
i/o thread, segment 1 the log i/o thread,
then follow the non-ibuf read threads, and as
the last are the non-ibuf write threads */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -4182,6 +4181,7 @@ os_aio_refresh_stats(void)
os_last_printout = time(NULL);
}
+#ifdef UNIV_DEBUG
/**************************************************************************
Checks that all slots in the system have been freed, that is, there are
no pending io operations. */
@@ -4241,3 +4241,4 @@ os_aio_all_slots_free(void)
return(FALSE);
}
+#endif /* UNIV_DEBUG */
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index 7738f5a34f0..df6d898d4ac 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -129,7 +129,7 @@ page_cur_try_search_shortcut(
#endif
success = TRUE;
exit_func:
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(success);
@@ -451,7 +451,7 @@ page_cur_search_with_match(
*iup_matched_bytes = up_matched_bytes;
*ilow_matched_fields = low_matched_fields;
*ilow_matched_bytes = low_matched_bytes;
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -515,8 +515,12 @@ page_cur_insert_rec_write_log(
byte* log_ptr;
byte* log_end;
ulint i;
+ ulint comp;
ut_a(rec_size < UNIV_PAGE_SIZE);
+ ut_ad(buf_frame_align(insert_rec) == buf_frame_align(cursor_rec));
+ ut_ad(!page_rec_is_comp(insert_rec) == !index->table->comp);
+ comp = page_rec_is_comp(insert_rec);
{
mem_heap_t* heap = NULL;
@@ -539,7 +543,7 @@ page_cur_insert_rec_write_log(
ut_ad(rec_size == rec_offs_size(ins_offs));
cur_rec_size = rec_offs_size(cur_offs);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -565,7 +569,7 @@ page_cur_insert_rec_write_log(
ins_ptr++;
cur_ptr++;
} else if ((i < extra_size)
- && (i >= extra_size - (index->table->comp
+ && (i >= extra_size - (comp
? REC_N_NEW_EXTRA_BYTES
: REC_N_OLD_EXTRA_BYTES))) {
i = extra_size;
@@ -580,7 +584,7 @@ page_cur_insert_rec_write_log(
if (mtr_get_log_mode(mtr) != MTR_LOG_SHORT_INSERTS) {
log_ptr = mlog_open_and_write_index(mtr, insert_rec, index,
- index->table->comp
+ comp
? MLOG_COMP_REC_INSERT : MLOG_REC_INSERT,
2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
@@ -605,8 +609,8 @@ page_cur_insert_rec_write_log(
log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
}
- if ((rec_get_info_and_status_bits(insert_rec, index->table->comp) !=
- rec_get_info_and_status_bits(cursor_rec, index->table->comp))
+ if ((rec_get_info_and_status_bits(insert_rec, comp) !=
+ rec_get_info_and_status_bits(cursor_rec, comp))
|| (extra_size != cur_extra_size)
|| (rec_size != cur_rec_size)) {
@@ -622,8 +626,7 @@ page_cur_insert_rec_write_log(
if (extra_info_yes) {
/* Write the info bits */
mach_write_to_1(log_ptr,
- rec_get_info_and_status_bits(insert_rec,
- index->table->comp));
+ rec_get_info_and_status_bits(insert_rec, comp));
log_ptr++;
/* Write the record origin offset */
@@ -757,6 +760,8 @@ page_cur_parse_insert_rec(
return(ptr + end_seg_len);
}
+ ut_ad(!!page_is_comp(page) == index->table->comp);
+
/* Read from the log the inserted index record end segment which
differs from the cursor record */
@@ -771,7 +776,7 @@ page_cur_parse_insert_rec(
if (extra_info_yes == 0) {
info_and_status_bits = rec_get_info_and_status_bits(
- cursor_rec, index->table->comp);
+ cursor_rec, page_is_comp(page));
origin_offset = rec_offs_extra_size(offsets);
mismatch_index = rec_offs_size(offsets) - end_seg_len;
}
@@ -807,7 +812,7 @@ page_cur_parse_insert_rec(
ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index);
ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
- rec_set_info_and_status_bits(buf + origin_offset, index->table->comp,
+ rec_set_info_and_status_bits(buf + origin_offset, page_is_comp(page),
info_and_status_bits);
page_cur_position(cursor_rec, &cursor);
@@ -821,7 +826,7 @@ page_cur_parse_insert_rec(
mem_free(buf);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -861,7 +866,7 @@ page_cur_insert_rec_low(
rec_t* owner_rec;
ulint n_owned;
mem_heap_t* heap = NULL;
- ibool comp = index->table->comp;
+ ulint comp;
ut_ad(cursor && mtr);
ut_ad(tuple || rec);
@@ -869,8 +874,8 @@ page_cur_insert_rec_low(
ut_ad(rec || dtuple_check_typed(tuple));
page = page_cur_get_page(cursor);
-
- ut_ad(page_is_comp(page) == comp);
+ comp = page_is_comp(page);
+ ut_ad(index->table->comp == !!comp);
ut_ad(cursor->rec != page_get_supremum_rec(page));
@@ -890,7 +895,7 @@ page_cur_insert_rec_low(
insert_buf = page_mem_alloc(page, rec_size, index, &heap_no);
if (insert_buf == NULL) {
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(NULL);
@@ -980,7 +985,7 @@ page_cur_insert_rec_low(
page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec,
index, mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(insert_rec);
@@ -1000,8 +1005,10 @@ page_copy_rec_list_to_created_page_write_log(
{
byte* log_ptr;
+ ut_ad(!!page_is_comp(page) == index->table->comp);
+
log_ptr = mlog_open_and_write_index(mtr, page, index,
- index->table->comp
+ page_is_comp(page)
? MLOG_COMP_LIST_END_COPY_CREATED
: MLOG_LIST_END_COPY_CREATED, 4);
ut_a(log_ptr);
@@ -1084,7 +1091,7 @@ page_copy_rec_list_end_to_created_page(
ulint log_mode;
byte* log_ptr;
ulint log_data_len;
- ibool comp = page_is_comp(page);
+ ulint comp = page_is_comp(page);
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -1186,7 +1193,7 @@ page_copy_rec_list_end_to_created_page(
slot_index--;
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -1230,8 +1237,10 @@ page_cur_delete_rec_write_log(
{
byte* log_ptr;
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
+
log_ptr = mlog_open_and_write_index(mtr, rec, index,
- index->table->comp
+ page_rec_is_comp(rec)
? MLOG_COMP_REC_DELETE
: MLOG_REC_DELETE, 2);
@@ -1242,7 +1251,7 @@ page_cur_delete_rec_write_log(
}
/* Write the cursor rec offset as a 2-byte ulint */
- mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
mlog_close(mtr, log_ptr + 2);
}
@@ -1285,7 +1294,7 @@ page_cur_parse_delete_rec(
page_cur_delete_rec(&cursor, index,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap), mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -1320,6 +1329,7 @@ page_cur_delete_rec(
page = page_cur_get_page(cursor);
current_rec = cursor->rec;
ut_ad(rec_offs_validate(current_rec, index, offsets));
+ ut_ad(!!page_is_comp(page) == index->table->comp);
/* The record must not be the supremum or infimum record. */
ut_ad(current_rec != page_get_supremum_rec(page));
diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c
index f3217e91f58..7e09cdf073e 100644
--- a/innobase/page/page0page.c
+++ b/innobase/page/page0page.c
@@ -72,65 +72,70 @@ page_dir_find_owner_slot(
/* out: the directory slot number */
rec_t* rec) /* in: the physical record */
{
- ulint i;
- ulint steps = 0;
- page_t* page;
- page_dir_slot_t* slot;
- rec_t* original_rec = rec;
- ibool comp;
-
+ page_t* page;
+ register uint16 rec_offs_bytes;
+ register page_dir_slot_t* slot;
+ register const page_dir_slot_t* first_slot;
+ register rec_t* r = rec;
+
ut_ad(page_rec_check(rec));
page = buf_frame_align(rec);
- comp = page_is_comp(page);
-
- while (rec_get_n_owned(rec, comp) == 0) {
- steps++;
- rec = page_rec_get_next(rec);
+ first_slot = page_dir_get_nth_slot(page, 0);
+ slot = page_dir_get_nth_slot(page, page_dir_get_n_slots(page) - 1);
+
+ if (page_is_comp(page)) {
+ while (rec_get_n_owned(r, TRUE) == 0) {
+ r = page + rec_get_next_offs(r, TRUE);
+ ut_ad(r >= page + PAGE_NEW_SUPREMUM);
+ ut_ad(r < page + (UNIV_PAGE_SIZE - PAGE_DIR));
+ }
+ } else {
+ while (rec_get_n_owned(r, FALSE) == 0) {
+ r = page + rec_get_next_offs(r, FALSE);
+ ut_ad(r >= page + PAGE_OLD_SUPREMUM);
+ ut_ad(r < page + (UNIV_PAGE_SIZE - PAGE_DIR));
+ }
}
-
- page = buf_frame_align(rec);
- i = page_dir_get_n_slots(page) - 1;
- slot = page_dir_get_nth_slot(page, i);
+ rec_offs_bytes = mach_encode_2(r - page);
- while (page_dir_slot_get_rec(slot) != rec) {
+ while (UNIV_LIKELY(*(uint16*) slot != rec_offs_bytes)) {
- if (i == 0) {
+ if (UNIV_UNLIKELY(slot == first_slot)) {
fprintf(stderr,
"InnoDB: Probable data corruption on page %lu\n"
"InnoDB: Original record ",
(ulong) buf_frame_get_page_no(page));
- if (comp) {
+ if (page_is_comp(page)) {
fputs("(compact record)", stderr);
} else {
- rec_print_old(stderr, original_rec);
+ rec_print_old(stderr, rec);
}
- fprintf(stderr, "\n"
- "InnoDB: on that page. Steps %lu.\n", (ulong) steps);
- fputs(
+ fputs("\n"
+ "InnoDB: on that page.\n"
"InnoDB: Cannot find the dir slot for record ",
stderr);
- if (comp) {
+ if (page_is_comp(page)) {
fputs("(compact record)", stderr);
} else {
- rec_print_old(stderr, rec);
+ rec_print_old(stderr, page
+ + mach_decode_2(rec_offs_bytes));
}
fputs("\n"
"InnoDB: on that page!\n", stderr);
buf_page_print(page);
- ut_error;
- }
+ ut_error;
+ }
- i--;
- slot = page_dir_get_nth_slot(page, i);
+ slot += PAGE_DIR_SLOT_SIZE;
}
- return(i);
+ return(((ulint) (first_slot - slot)) / PAGE_DIR_SLOT_SIZE);
}
/******************************************************************
@@ -252,13 +257,13 @@ page_mem_alloc(
*heap_no = rec_get_heap_no(rec, page_is_comp(page));
block = rec_get_start(rec, offsets);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(block);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -290,7 +295,7 @@ page_create_write_log(
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
mtr_t* mtr, /* in: mini-transaction handle */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
{
mlog_write_initial_log_record(frame,
comp ? MLOG_COMP_PAGE_CREATE : MLOG_PAGE_CREATE, mtr);
@@ -305,7 +310,7 @@ page_parse_create(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr __attribute__((unused)), /* in: buffer end */
- ibool comp, /* in: TRUE=compact page format */
+ ulint comp, /* in: nonzero=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -330,7 +335,7 @@ page_create(
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
mtr_t* mtr, /* in: mini-transaction handle */
- ibool comp) /* in: TRUE=compact page format */
+ ulint comp) /* in: nonzero=compact page format */
{
page_dir_slot_t* slot;
mem_heap_t* heap;
@@ -396,9 +401,9 @@ page_create(
dtuple_set_info_bits(tuple, REC_STATUS_SUPREMUM);
field = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(field, "supremum", 9 - comp);
+ dfield_set_data(field, "supremum", comp ? 8 : 9);
dtype_set(dfield_get_type(field),
- DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, 9 - comp, 0);
+ DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, comp ? 8 : 9, 0);
supremum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple);
@@ -478,10 +483,11 @@ page_copy_rec_list_end_no_locks(
page_cur_move_to_next(&cur1);
}
- ut_a(index->table->comp == page_is_comp(page));
- ut_a(index->table->comp == page_is_comp(new_page));
+ ut_a((ibool)!!page_is_comp(new_page) == index->table->comp);
+ ut_a(page_is_comp(new_page) == page_is_comp(page));
ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == (ulint)
- (index->table->comp ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
+ (page_is_comp(new_page)
+ ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
page_cur_set_before_first(new_page, &cur2);
@@ -489,12 +495,15 @@ page_copy_rec_list_end_no_locks(
sup = page_get_supremum_rec(page);
- while (sup != page_cur_get_rec(&cur1)) {
+ for (;;) {
rec_t* cur1_rec = page_cur_get_rec(&cur1);
+ if (cur1_rec == sup) {
+ break;
+ }
offsets = rec_get_offsets(cur1_rec, index, offsets,
ULINT_UNDEFINED, &heap);
- if (!page_cur_rec_insert(&cur2, cur1_rec, index,
- offsets, mtr)) {
+ if (UNIV_UNLIKELY(!page_cur_rec_insert(&cur2, cur1_rec, index,
+ offsets, mtr))) {
/* Track an assertion failure reported on the mailing
list on June 18th, 2003 */
@@ -514,7 +523,7 @@ page_copy_rec_list_end_no_locks(
page_cur_move_to_next(&cur2);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -608,7 +617,7 @@ page_copy_rec_list_start(
btr_search_move_or_delete_hash_entries(new_page, page, index);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -619,7 +628,6 @@ UNIV_INLINE
void
page_delete_rec_list_write_log(
/*===========================*/
- page_t* page, /* in: index page */
rec_t* rec, /* in: record on page */
dict_index_t* index, /* in: record descriptor */
byte type, /* in: operation type:
@@ -632,10 +640,10 @@ page_delete_rec_list_write_log(
|| type == MLOG_COMP_LIST_END_DELETE
|| type == MLOG_COMP_LIST_START_DELETE);
- log_ptr = mlog_open_and_write_index(mtr, page, index, type, 2);
+ log_ptr = mlog_open_and_write_index(mtr, rec, index, type, 2);
if (log_ptr) {
/* Write the parameter as a 2-byte ulint */
- mach_write_to_2(log_ptr, rec - page);
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
mlog_close(mtr, log_ptr + 2);
}
}
@@ -679,6 +687,8 @@ page_parse_delete_rec_list(
return(ptr);
}
+ ut_ad(!!page_is_comp(page) == index->table->comp);
+
if (type == MLOG_LIST_END_DELETE
|| type == MLOG_COMP_LIST_END_DELETE) {
page_delete_rec_list_end(page, page + offset, index,
@@ -716,7 +726,7 @@ page_delete_rec_list_end(
ulint count;
ulint n_owned;
rec_t* sup;
- ibool comp;
+ ulint comp;
/* Reset the last insert info in the page header and increment
the modify clock for the frame */
@@ -731,12 +741,12 @@ page_delete_rec_list_end(
sup = page_get_supremum_rec(page);
- if (rec == page_get_infimum_rec(page)) {
+ comp = page_is_comp(page);
+ if (page_rec_is_infimum_low(rec - page)) {
rec = page_rec_get_next(rec);
}
- comp = page_is_comp(page);
- page_delete_rec_list_write_log(page, rec, index,
+ page_delete_rec_list_write_log(rec, index,
comp ? MLOG_COMP_LIST_END_DELETE : MLOG_LIST_END_DELETE, mtr);
if (rec == sup) {
@@ -772,7 +782,7 @@ page_delete_rec_list_end(
rec2 = page_rec_get_next(rec2);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -841,13 +851,15 @@ page_delete_rec_list_start(
byte type;
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
- if (index->table->comp) {
+ ut_ad(!!page_is_comp(page) == index->table->comp);
+
+ if (page_is_comp(page)) {
type = MLOG_COMP_LIST_START_DELETE;
} else {
type = MLOG_LIST_START_DELETE;
}
- page_delete_rec_list_write_log(page, rec, index, type, mtr);
+ page_delete_rec_list_write_log(rec, index, type, mtr);
page_cur_set_before_first(page, &cur1);
@@ -868,7 +880,7 @@ page_delete_rec_list_start(
page_cur_delete_rec(&cur1, index, offsets, mtr);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -1221,7 +1233,7 @@ page_rec_get_n_recs_before(
rec_t* slot_rec;
page_t* page;
ulint i;
- ibool comp;
+ ulint comp;
lint n = 0;
ut_ad(page_rec_check(rec));
@@ -1264,9 +1276,9 @@ page_rec_print(
rec_t* rec, /* in: physical record */
const ulint* offsets)/* in: record descriptor */
{
- ibool comp = page_is_comp(buf_frame_align(rec));
+ ulint comp = page_is_comp(buf_frame_align(rec));
- ut_a(comp == rec_offs_comp(offsets));
+ ut_a(!comp == !rec_offs_comp(offsets));
rec_print_new(stderr, rec, offsets);
fprintf(stderr,
" n_owned: %lu; heap_no: %lu; next rec: %lu\n",
@@ -1335,7 +1347,7 @@ page_print_list(
ulint* offsets = offsets_;
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
- ut_a(page_is_comp(page) == index->table->comp);
+ ut_a((ibool)!!page_is_comp(page) == index->table->comp);
fprintf(stderr,
"--------------------------------\n"
@@ -1381,7 +1393,7 @@ page_print_list(
"--------------------------------\n",
(ulong) (count + 1));
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -1447,11 +1459,11 @@ page_rec_validate(
ulint n_owned;
ulint heap_no;
page_t* page;
- ibool comp;
+ ulint comp;
page = buf_frame_align(rec);
comp = page_is_comp(page);
- ut_a(comp == rec_offs_comp(offsets));
+ ut_a(!comp == !rec_offs_comp(offsets));
page_rec_check(rec);
rec_validate(rec, offsets);
@@ -1528,7 +1540,7 @@ page_simple_validate(
ulint count;
ulint own_count;
ibool ret = FALSE;
- ibool comp = page_is_comp(page);
+ ulint comp = page_is_comp(page);
/* Check first that the record heap and the directory do not
overlap. */
@@ -1725,11 +1737,11 @@ page_validate(
ulint n_slots;
ibool ret = FALSE;
ulint i;
- ibool comp = page_is_comp(page);
+ ulint comp = page_is_comp(page);
ulint* offsets = NULL;
ulint* old_offsets = NULL;
- if (comp != index->table->comp) {
+ if ((ibool)!!comp != index->table->comp) {
fputs("InnoDB: 'compact format' flag mismatch\n", stderr);
goto func_exit2;
}
@@ -1743,9 +1755,7 @@ page_validate(
records in the page record heap do not overlap */
buf = mem_heap_alloc(heap, UNIV_PAGE_SIZE);
- for (i = 0; i < UNIV_PAGE_SIZE; i++) {
- buf[i] = 0;
- }
+ memset(buf, 0, UNIV_PAGE_SIZE);
/* Check first that the record heap and the directory do not
overlap. */
@@ -1810,8 +1820,7 @@ page_validate(
}
}
- if ((rec != page_get_supremum_rec(page))
- && (rec != page_get_infimum_rec(page))) {
+ if (page_rec_is_user_rec(rec)) {
data_size += rec_offs_size(offsets);
}
diff --git a/innobase/pars/lexyy.c b/innobase/pars/lexyy.c
index 0112f618533..1145ca295e7 100644
--- a/innobase/pars/lexyy.c
+++ b/innobase/pars/lexyy.c
@@ -616,6 +616,9 @@ How to make the InnoDB parser and lexer C files:
7. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c
(Needed for AIX)
+8. Add a type cast to int to the assignment below the comment
+ 'need more input.' (Removes a warning on Win64)
+
These instructions seem to work at least with bison-1.28 and flex-2.5.4 on
Linux.
*******************************************************/
@@ -2114,7 +2117,7 @@ static int input()
else
{ /* need more input */
- int offset = yy_c_buf_p - yytext_ptr;
+ int offset = (int) (yy_c_buf_p - yytext_ptr);
++yy_c_buf_p;
switch ( yy_get_next_buffer() )
diff --git a/innobase/pars/pars0lex.l b/innobase/pars/pars0lex.l
index 811057d48a1..e481634f77e 100644
--- a/innobase/pars/pars0lex.l
+++ b/innobase/pars/pars0lex.l
@@ -31,6 +31,9 @@ How to make the InnoDB parser and lexer C files:
7. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c
(Needed for AIX)
+8. Add a type cast to int to the assignment below the comment
+ 'need more input.' (Removes a warning on Win64)
+
These instructions seem to work at least with bison-1.28 and flex-2.5.4 on
Linux.
*******************************************************/
diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c
index 74348b865a8..7c33476fb9e 100644
--- a/innobase/rem/rem0cmp.c
+++ b/innobase/rem/rem0cmp.c
@@ -320,7 +320,7 @@ cmp_data_data_slow(
|| (cur_type->mtype == DATA_BLOB
&& 0 == (cur_type->prtype & DATA_BINARY_TYPE)
&& dtype_get_charset_coll(cur_type->prtype) !=
- data_mysql_latin1_swedish_charset_coll)) {
+ DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
return(cmp_whole_field(cur_type,
data1, (unsigned) len1,
@@ -451,6 +451,20 @@ cmp_dtuple_rec_with_match(
ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
ut_ad(cur_field <= rec_offs_n_fields(offsets));
+ if (cur_bytes == 0 && cur_field == 0) {
+ ulint rec_info = rec_get_info_bits(rec,
+ rec_offs_comp(offsets));
+ ulint tup_info = dtuple_get_info_bits(dtuple);
+
+ if (rec_info & REC_INFO_MIN_REC_FLAG) {
+ ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
+ goto order_resolved;
+ } else if (tup_info & REC_INFO_MIN_REC_FLAG) {
+ ret = -1;
+ goto order_resolved;
+ }
+ }
+
/* Match fields in a loop; stop if we run out of fields in dtuple
or find an externally stored field */
@@ -469,32 +483,7 @@ cmp_dtuple_rec_with_match(
the predefined minimum record, or the field is externally
stored */
- if (cur_bytes == 0) {
- if (cur_field == 0) {
-
- if (rec_get_info_bits(rec,
- rec_offs_comp(offsets))
- & REC_INFO_MIN_REC_FLAG) {
-
- if (dtuple_get_info_bits(dtuple)
- & REC_INFO_MIN_REC_FLAG) {
-
- ret = 0;
- } else {
- ret = 1;
- }
-
- goto order_resolved;
- }
-
- if (dtuple_get_info_bits(dtuple)
- & REC_INFO_MIN_REC_FLAG) {
- ret = -1;
-
- goto order_resolved;
- }
- }
-
+ if (UNIV_LIKELY(cur_bytes == 0)) {
if (rec_offs_nth_extern(offsets, cur_field)) {
/* We do not compare to an externally
stored field */
@@ -504,24 +493,20 @@ cmp_dtuple_rec_with_match(
goto order_resolved;
}
- if (dtuple_f_len == UNIV_SQL_NULL
- || rec_f_len == UNIV_SQL_NULL) {
-
- if (dtuple_f_len == rec_f_len) {
+ if (dtuple_f_len == UNIV_SQL_NULL) {
+ if (rec_f_len == UNIV_SQL_NULL) {
goto next_field;
}
- if (rec_f_len == UNIV_SQL_NULL) {
- /* We define the SQL null to be the
- smallest possible value of a field
- in the alphabetical order */
-
- ret = 1;
- } else {
- ret = -1;
- }
+ ret = -1;
+ goto order_resolved;
+ } else if (rec_f_len == UNIV_SQL_NULL) {
+ /* We define the SQL null to be the
+ smallest possible value of a field
+ in the alphabetical order */
+ ret = 1;
goto order_resolved;
}
}
@@ -530,7 +515,7 @@ cmp_dtuple_rec_with_match(
|| (cur_type->mtype == DATA_BLOB
&& 0 == (cur_type->prtype & DATA_BINARY_TYPE)
&& dtype_get_charset_coll(cur_type->prtype) !=
- data_mysql_latin1_swedish_charset_coll)) {
+ DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
ret = cmp_whole_field(
cur_type,
@@ -555,7 +540,7 @@ cmp_dtuple_rec_with_match(
/* Compare then the fields */
for (;;) {
- if (rec_f_len <= cur_bytes) {
+ if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
if (dtuple_f_len <= cur_bytes) {
goto next_field;
@@ -572,7 +557,7 @@ cmp_dtuple_rec_with_match(
rec_byte = *rec_b_ptr;
}
- if (dtuple_f_len <= cur_bytes) {
+ if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
dtuple_byte = dtype_get_pad_char(cur_type);
if (dtuple_byte == ULINT_UNDEFINED) {
@@ -600,14 +585,16 @@ cmp_dtuple_rec_with_match(
rec_byte = cmp_collate(rec_byte);
dtuple_byte = cmp_collate(dtuple_byte);
}
-
- if (dtuple_byte > rec_byte) {
- ret = 1;
- goto order_resolved;
- } else if (dtuple_byte < rec_byte) {
- ret = -1;
- goto order_resolved;
+ ret = dtuple_byte - rec_byte;
+ if (UNIV_UNLIKELY(ret)) {
+ if (ret < 0) {
+ ret = -1;
+ goto order_resolved;
+ } else {
+ ret = 1;
+ goto order_resolved;
+ }
}
next_byte:
/* Next byte */
@@ -740,7 +727,7 @@ cmp_rec_rec_with_match(
ulint cur_bytes; /* number of already matched bytes in current
field */
int ret = 3333; /* return value */
- ibool comp;
+ ulint comp;
ut_ad(rec1 && rec2 && index);
ut_ad(rec_offs_validate(rec1, index, offsets1));
@@ -832,7 +819,7 @@ cmp_rec_rec_with_match(
|| (cur_type->mtype == DATA_BLOB
&& 0 == (cur_type->prtype & DATA_BINARY_TYPE)
&& dtype_get_charset_coll(cur_type->prtype) !=
- data_mysql_latin1_swedish_charset_coll)) {
+ DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
ret = cmp_whole_field(cur_type,
rec1_b_ptr, (unsigned) rec1_f_len,
@@ -983,12 +970,8 @@ cmp_debug_dtuple_rec_with_match(
if (rec_get_info_bits(rec, rec_offs_comp(offsets))
& REC_INFO_MIN_REC_FLAG) {
- if (dtuple_get_info_bits(dtuple)
- & REC_INFO_MIN_REC_FLAG) {
- ret = 0;
- } else {
- ret = 1;
- }
+ ret = !(dtuple_get_info_bits(dtuple)
+ & REC_INFO_MIN_REC_FLAG);
goto order_resolved;
}
diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c
index 542c746209b..580a7bfe509 100644
--- a/innobase/rem/rem0rec.c
+++ b/innobase/rem/rem0rec.c
@@ -159,22 +159,20 @@ rec_init_offsets(
ulint* offsets)/* in/out: array of offsets;
in: n=rec_offs_n_fields(offsets) */
{
- ulint n_fields = rec_offs_n_fields(offsets);
ulint i = 0;
ulint offs;
rec_offs_make_valid(rec, index, offsets);
- if (index->table->comp) {
+ if (UNIV_LIKELY(index->table->comp)) {
const byte* nulls;
const byte* lens;
dict_field_t* field;
- dtype_t* type;
ulint null_mask;
ulint status = rec_get_status(rec);
ulint n_node_ptr_field = ULINT_UNDEFINED;
- switch (status) {
+ switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
case REC_STATUS_INFIMUM:
case REC_STATUS_SUPREMUM:
/* the field is 8 bytes long */
@@ -196,56 +194,69 @@ rec_init_offsets(
null_mask = 1;
/* read the lengths of fields 0..n */
- for (; i < n_fields; i++) {
- ibool is_null = FALSE, is_external = FALSE;
+ do {
ulint len;
- if (i == n_node_ptr_field) {
- len = 4;
+ if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
+ len = offs += 4;
goto resolved;
}
field = dict_index_get_nth_field(index, i);
- type = dict_col_get_type(dict_field_get_col(field));
- if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+ if (!(dtype_get_prtype(dict_col_get_type(
+ dict_field_get_col(field)))
+ & DATA_NOT_NULL)) {
/* nullable field => read the null flag */
- is_null = (*nulls & null_mask) != 0;
- null_mask <<= 1;
- if (null_mask == 0x100) {
+
+ if (UNIV_UNLIKELY(!(byte) null_mask)) {
nulls--;
null_mask = 1;
}
+
+ if (*nulls & null_mask) {
+ null_mask <<= 1;
+ /* No length is stored for NULL fields.
+ We do not advance offs, and we set
+ the length to zero and enable the
+ SQL NULL flag in offsets[]. */
+ len = offs | REC_OFFS_SQL_NULL;
+ goto resolved;
+ }
+ null_mask <<= 1;
}
- if (is_null) {
- /* No length is stored for NULL fields. */
- len = 0;
- } else if (!field->fixed_len) {
+ if (UNIV_UNLIKELY(!field->fixed_len)) {
/* Variable-length field: read the length */
+ dtype_t* type = dict_col_get_type(
+ dict_field_get_col(field));
len = *lens--;
- if (dtype_get_len(type) > 255
- || dtype_get_mtype(type) == DATA_BLOB) {
+ if (UNIV_UNLIKELY(dtype_get_len(type) > 255)
+ || UNIV_UNLIKELY(dtype_get_mtype(type)
+ == DATA_BLOB)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */
- is_external = !!(len & 0x40);
- len &= 0x3f;
len <<= 8;
len |= *lens--;
+
+ offs += len & 0x3fff;
+ if (UNIV_UNLIKELY(len
+ & 0x4000)) {
+ len = offs
+ | REC_OFFS_EXTERNAL;
+ } else {
+ len = offs;
+ }
+
+ goto resolved;
}
}
+
+ len = offs += len;
} else {
- len = field->fixed_len;
+ len = offs += field->fixed_len;
}
resolved:
- offs += len;
- len = offs;
- if (is_external) {
- len |= REC_OFFS_EXTERNAL;
- }
- if (is_null) {
- len |= REC_OFFS_SQL_NULL;
- }
rec_offs_base(offsets)[i + 1] = len;
- }
+ } while (++i < rec_offs_n_fields(offsets));
*rec_offs_base(offsets) =
(rec - (lens + 1)) | REC_OFFS_COMPACT;
@@ -253,22 +264,22 @@ rec_init_offsets(
/* Old-style record: determine extra size and end offsets */
offs = REC_N_OLD_EXTRA_BYTES;
if (rec_get_1byte_offs_flag(rec)) {
- offs += n_fields;
+ offs += rec_offs_n_fields(offsets);
*rec_offs_base(offsets) = offs;
/* Determine offsets to fields */
- for (; i < n_fields; i++) {
+ do {
offs = rec_1_get_field_end_info(rec, i);
if (offs & REC_1BYTE_SQL_NULL_MASK) {
offs &= ~REC_1BYTE_SQL_NULL_MASK;
offs |= REC_OFFS_SQL_NULL;
}
rec_offs_base(offsets)[1 + i] = offs;
- }
+ } while (++i < rec_offs_n_fields(offsets));
} else {
- offs += 2 * n_fields;
+ offs += 2 * rec_offs_n_fields(offsets);
*rec_offs_base(offsets) = offs;
/* Determine offsets to fields */
- for (; i < n_fields; i++) {
+ do {
offs = rec_2_get_field_end_info(rec, i);
if (offs & REC_2BYTE_SQL_NULL_MASK) {
offs &= ~REC_2BYTE_SQL_NULL_MASK;
@@ -279,7 +290,7 @@ rec_init_offsets(
offs |= REC_OFFS_EXTERNAL;
}
rec_offs_base(offsets)[1 + i] = offs;
- }
+ } while (++i < rec_offs_n_fields(offsets));
}
}
}
@@ -310,8 +321,9 @@ rec_get_offsets_func(
ut_ad(index);
ut_ad(heap);
- if (index->table->comp) {
- switch (rec_get_status(rec)) {
+ if (UNIV_LIKELY(index->table->comp)) {
+ switch (UNIV_EXPECT(rec_get_status(rec),
+ REC_STATUS_ORDINARY)) {
case REC_STATUS_ORDINARY:
n = dict_index_get_n_fields(index);
break;
@@ -331,13 +343,14 @@ rec_get_offsets_func(
n = rec_get_n_fields_old(rec);
}
- if (n_fields < n) {
+ if (UNIV_UNLIKELY(n_fields < n)) {
n = n_fields;
}
size = n + (1 + REC_OFFS_HEADER_SIZE);
- if (!offsets || rec_offs_get_n_alloc(offsets) < size) {
+ if (UNIV_UNLIKELY(!offsets) ||
+ UNIV_UNLIKELY(rec_offs_get_n_alloc(offsets) < size)) {
if (!*heap) {
*heap = mem_heap_create_func(size * sizeof(ulint),
NULL, MEM_HEAP_DYNAMIC, file, line);
@@ -652,9 +665,17 @@ rec_set_field_extern_bits(
to log about the change */
{
ulint i;
-
- for (i = 0; i < n_fields; i++) {
- rec_set_nth_field_extern_bit(rec, index, vec[i], TRUE, mtr);
+
+ if (UNIV_LIKELY(index->table->comp)) {
+ for (i = 0; i < n_fields; i++) {
+ rec_set_nth_field_extern_bit_new(rec, index, vec[i],
+ TRUE, mtr);
+ }
+ } else {
+ for (i = 0; i < n_fields; i++) {
+ rec_set_nth_field_extern_bit_old(rec, vec[i],
+ TRUE, mtr);
+ }
}
}
@@ -949,7 +970,7 @@ rec_convert_dtuple_to_rec(
ut_ad(dtuple_validate(dtuple));
ut_ad(dtuple_check_typed(dtuple));
- if (index->table->comp) {
+ if (UNIV_LIKELY(index->table->comp)) {
rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple);
} else {
rec = rec_convert_dtuple_to_rec_old(buf, dtuple);
@@ -965,7 +986,7 @@ rec_convert_dtuple_to_rec(
offsets = rec_get_offsets(rec, index,
offsets_, ULINT_UNDEFINED, &heap);
ut_ad(rec_validate(rec, offsets));
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -1078,17 +1099,19 @@ rec_copy_prefix_to_buf(
for the copied prefix, or NULL */
ulint* buf_size) /* in/out: buffer size */
{
- byte* nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
- byte* lens = nulls - (index->n_nullable + 7) / 8;
+ byte* nulls;
+ byte* lens;
dict_field_t* field;
dtype_t* type;
ulint i;
- ulint prefix_len = 0;
+ ulint prefix_len;
ibool is_null;
- ulint null_mask = 1;
+ ulint null_mask;
ulint status;
- if (!index->table->comp) {
+ UNIV_PREFETCH_RW(*buf);
+
+ if (UNIV_UNLIKELY(!index->table->comp)) {
ut_ad(rec_validate_old(rec));
return(rec_copy_prefix_to_buf_old(rec, n_fields,
rec_get_field_start_offs(rec, n_fields),
@@ -1109,10 +1132,16 @@ rec_copy_prefix_to_buf(
case REC_STATUS_SUPREMUM:
/* infimum or supremum record: no sense to copy anything */
default:
- ut_a(0);
+ ut_error;
return(NULL);
}
+ nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+ lens = nulls - (index->n_nullable + 7) / 8;
+ UNIV_PREFETCH_R(lens);
+ prefix_len = 0;
+ null_mask = 1;
+
/* read the lengths of fields 0..n */
for (i = 0; i < n_fields; i++) {
field = dict_index_get_nth_field(index, i);
@@ -1122,8 +1151,11 @@ rec_copy_prefix_to_buf(
/* nullable field => read the null flag */
is_null = !!(*nulls & null_mask);
null_mask <<= 1;
- if (null_mask == 0x100)
- nulls--, null_mask = 1;
+ if (null_mask == 0x100) {
+ --nulls;
+ UNIV_PREFETCH_R(nulls);
+ null_mask = 1;
+ }
}
if (is_null) {
@@ -1138,12 +1170,15 @@ rec_copy_prefix_to_buf(
len &= 0x3f;
len <<= 8;
len |= *lens--;
+ UNIV_PREFETCH_R(lens);
}
}
prefix_len += len;
}
}
+ UNIV_PREFETCH_R(rec + prefix_len);
+
prefix_len += rec - (lens + 1);
if ((*buf == NULL) || (*buf_size < prefix_len)) {
@@ -1412,7 +1447,7 @@ rec_print(
rec_print_new(file, rec, rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap));
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 303fe5749bc..bce775c25d6 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -478,7 +478,7 @@ row_ins_cascade_calc_update_vec(
if (parent_ufield->field_no == parent_field_no) {
- ulint fixed_size;
+ ulint min_size;
/* A field in the parent index record is
updated. Let us make the update vector
@@ -508,10 +508,13 @@ row_ins_cascade_calc_update_vec(
column, do not allow the update */
if (ufield->new_val.len != UNIV_SQL_NULL
- && ufield->new_val.len
- > dtype_get_len(type)) {
+ && dtype_get_at_most_n_mbchars(
+ type, dtype_get_len(type),
+ ufield->new_val.len,
+ ufield->new_val.data)
+ < ufield->new_val.len) {
- return(ULINT_UNDEFINED);
+ return(ULINT_UNDEFINED);
}
/* If the parent column type has a different
@@ -519,29 +522,48 @@ row_ins_cascade_calc_update_vec(
need to pad with spaces the new value of the
child column */
- fixed_size = dtype_get_fixed_size(type);
-
- /* TODO: pad in UCS-2 with 0x0020.
- TODO: How does the special truncation of
- UTF-8 CHAR cols affect this? */
+ min_size = dtype_get_min_size(type);
- if (fixed_size
+ if (min_size
&& ufield->new_val.len != UNIV_SQL_NULL
- && ufield->new_val.len < fixed_size) {
+ && ufield->new_val.len < min_size) {
+ char* pad_start;
+ const char* pad_end;
ufield->new_val.data =
mem_heap_alloc(heap,
- fixed_size);
- ufield->new_val.len = fixed_size;
- ut_a(dtype_get_pad_char(type)
- != ULINT_UNDEFINED);
-
- memset(ufield->new_val.data,
- (byte)dtype_get_pad_char(type),
- fixed_size);
+ min_size);
+ pad_start =
+ ((char*) ufield->new_val.data)
+ + ufield->new_val.len;
+ pad_end =
+ ((char*) ufield->new_val.data)
+ + min_size;
+ ufield->new_val.len = min_size;
ut_memcpy(ufield->new_val.data,
parent_ufield->new_val.data,
parent_ufield->new_val.len);
+
+ switch (UNIV_EXPECT(
+ dtype_get_mbminlen(type), 1)) {
+ default:
+ ut_error;
+ case 1:
+ /* space=0x20 */
+ memset(pad_start, 0x20,
+ pad_end - pad_start);
+ break;
+ case 2:
+ /* space=0x0020 */
+ ut_a(!(ufield->new_val.len
+ % 2));
+ ut_a(!(min_size % 2));
+ do {
+ *pad_start++ = 0x00;
+ *pad_start++ = 0x20;
+ } while (pad_start < pad_end);
+ break;
+ }
}
ufield->extern_storage = FALSE;
@@ -1255,9 +1277,11 @@ run_again:
/* Scan index records and check if there is a matching record */
for (;;) {
+ page_t* page;
rec = btr_pcur_get_rec(&pcur);
+ page = buf_frame_align(rec);
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
+ if (rec == page_get_infimum_rec(page)) {
goto next_rec;
}
@@ -1265,7 +1289,7 @@ run_again:
offsets = rec_get_offsets(rec, check_index,
offsets, ULINT_UNDEFINED, &heap);
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
+ if (rec == page_get_supremum_rec(page)) {
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec,
check_index, offsets, thr);
@@ -1392,7 +1416,7 @@ do_possible_lock_wait:
}
exit_func:
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
@@ -1529,12 +1553,7 @@ row_ins_dupl_error_with_rec(
}
}
- if (!rec_get_deleted_flag(rec, index->table->comp)) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
}
/*******************************************************************
@@ -1561,7 +1580,6 @@ row_ins_scan_sec_index_for_duplicate(
ulint err = DB_SUCCESS;
ibool moved;
mtr_t mtr;
- trx_t* trx;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -1601,11 +1619,6 @@ row_ins_scan_sec_index_for_duplicate(
goto next_rec;
}
- /* Try to place a lock on the index record */
-
- trx = thr_get_trx(thr);
- ut_ad(trx);
-
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
@@ -1629,7 +1642,7 @@ row_ins_scan_sec_index_for_duplicate(
break;
}
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
+ if (page_rec_is_supremum(rec)) {
goto next_rec;
}
@@ -1660,7 +1673,7 @@ next_rec:
}
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
mtr_commit(&mtr);
@@ -1697,7 +1710,6 @@ row_ins_duplicate_error_in_clust(
#ifndef UNIV_HOTBACKUP
ulint err;
rec_t* rec;
- page_t* page;
ulint n_unique;
trx_t* trx = thr_get_trx(thr);
mem_heap_t*heap = NULL;
@@ -1728,9 +1740,8 @@ row_ins_duplicate_error_in_clust(
if (cursor->low_match >= n_unique) {
rec = btr_cur_get_rec(cursor);
- page = buf_frame_align(rec);
- if (rec != page_get_infimum_rec(page)) {
+ if (!page_rec_is_infimum(rec)) {
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
@@ -1772,9 +1783,8 @@ row_ins_duplicate_error_in_clust(
if (cursor->up_match >= n_unique) {
rec = page_rec_get_next(btr_cur_get_rec(cursor));
- page = buf_frame_align(rec);
- if (rec != page_get_supremum_rec(page)) {
+ if (!page_rec_is_supremum(rec)) {
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
@@ -1842,7 +1852,6 @@ row_ins_must_modify(
{
ulint enough_match;
rec_t* rec;
- page_t* page;
/* NOTE: (compare to the note in row_ins_duplicate_error) Because node
pointers on upper levels of the B-tree may match more to entry than
@@ -1856,9 +1865,8 @@ row_ins_must_modify(
if (cursor->low_match >= enough_match) {
rec = btr_cur_get_rec(cursor);
- page = buf_frame_align(rec);
- if (rec != page_get_infimum_rec(page)) {
+ if (!page_rec_is_infimum(rec)) {
return(ROW_INS_PREV);
}
@@ -1897,7 +1905,6 @@ row_ins_index_entry_low(
ulint modify = 0; /* remove warning */
rec_t* insert_rec;
rec_t* rec;
- rec_t* first_rec;
ulint err;
ulint n_unique;
big_rec_t* big_rec = NULL;
@@ -1932,15 +1939,20 @@ row_ins_index_entry_low(
err = DB_SUCCESS;
goto function_exit;
- }
-
- first_rec = page_rec_get_next(page_get_infimum_rec(
- buf_frame_align(btr_cur_get_rec(&cursor))));
+ }
+
+#ifdef UNIV_DEBUG
+ {
+ page_t* page = btr_cur_get_page(&cursor);
+ rec_t* first_rec = page_rec_get_next(
+ page_get_infimum_rec(page));
- if (!page_rec_is_supremum(first_rec)) {
- ut_a(rec_get_n_fields(first_rec, index)
+ if (UNIV_LIKELY(first_rec != page_get_supremum_rec(page))) {
+ ut_a(rec_get_n_fields(first_rec, index)
== dtuple_get_n_fields(entry));
+ }
}
+#endif
n_unique = dict_index_get_n_unique(index);
@@ -2048,7 +2060,7 @@ function_exit:
mtr_commit(&mtr);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index fafbef4c999..eb50b83a4d5 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -265,7 +265,7 @@ row_mysql_store_col_in_innobase_format(
necessarily the length of the actual
payload data; if the column is a true
VARCHAR then this is irrelevant */
- ibool comp) /* in: TRUE = compact format */
+ ulint comp) /* in: nonzero=compact format */
{
byte* ptr = mysql_data;
dtype_t* dtype;
@@ -971,25 +971,6 @@ run_again:
}
/*************************************************************************
-Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
-lock type LOCK_TABLE_EXP). */
-
-void
-row_unlock_tables_for_mysql(
-/*========================*/
- trx_t* trx) /* in: transaction */
-{
- if (!trx->n_lock_table_exp) {
-
- return;
- }
-
- mutex_enter(&kernel_mutex);
- lock_release_tables_off_kernel(trx);
- mutex_exit(&kernel_mutex);
-}
-
-/*************************************************************************
Sets a table lock on the table mentioned in prebuilt. */
int
@@ -1000,9 +981,10 @@ row_lock_table_for_mysql(
table handle */
dict_table_t* table, /* in: table to lock, or NULL
if prebuilt->table should be
- locked or a
+ locked as
prebuilt->select_lock_type */
- ulint mode) /* in: lock mode of table */
+ ulint mode) /* in: lock mode of table
+ (ignored if table==NULL) */
{
trx_t* trx = prebuilt->trx;
que_thr_t* thr;
@@ -1038,14 +1020,8 @@ run_again:
if (table) {
err = lock_table(0, table, mode, thr);
} else {
- if (mode == LOCK_TABLE_TRANSACTIONAL) {
- err = lock_table(LOCK_TABLE_TRANSACTIONAL,
- prebuilt->table,
- prebuilt->select_lock_type, thr);
- } else {
- err = lock_table(LOCK_TABLE_EXP, prebuilt->table,
- prebuilt->select_lock_type, thr);
- }
+ err = lock_table(0, prebuilt->table,
+ prebuilt->select_lock_type, thr);
}
trx->error_state = err;
@@ -3858,7 +3834,7 @@ funct_exit:
que_graph_free(graph);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -3893,6 +3869,7 @@ row_scan_and_check_index(
int cmp;
ibool contains_null;
ulint i;
+ ulint cnt;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -3915,11 +3892,19 @@ row_scan_and_check_index(
dtuple_set_n_fields(prebuilt->search_tuple, 0);
prebuilt->select_lock_type = LOCK_NONE;
+ cnt = 1000;
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
loop:
+ /* Check thd->killed every 1,000 scanned rows */
+ if (--cnt == 0) {
+ if (trx_is_interrupted(prebuilt->trx)) {
+ goto func_exit;
+ }
+ cnt = 1000;
+ }
if (ret != DB_SUCCESS) {
-
+ func_exit:
mem_free(buf);
mem_heap_free(heap);
@@ -4046,7 +4031,7 @@ row_check_table_for_mysql(
ut_print_name(stderr, index->name);
putc('\n', stderr); */
- if (!btr_validate_tree(index->tree)) {
+ if (!btr_validate_tree(index->tree, prebuilt->trx)) {
ret = DB_ERROR;
} else {
if (!row_scan_and_check_index(prebuilt,
@@ -4054,6 +4039,10 @@ row_check_table_for_mysql(
ret = DB_ERROR;
}
+ if (trx_is_interrupted(prebuilt->trx)) {
+ break;
+ }
+
/* fprintf(stderr, "%lu entries in index %s\n", n_rows,
index->name); */
diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c
index 5893e016011..abcf97110d9 100644
--- a/innobase/row/row0purge.c
+++ b/innobase/row/row0purge.c
@@ -126,7 +126,7 @@ row_purge_remove_clust_if_poss_low(
if (0 != ut_dulint_cmp(node->roll_ptr,
row_get_rec_roll_ptr(rec, index, rec_get_offsets(
rec, index, offsets_, ULINT_UNDEFINED, &heap)))) {
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
/* Someone else has modified the record later: do not remove */
@@ -135,7 +135,7 @@ row_purge_remove_clust_if_poss_low(
return(TRUE);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
diff --git a/innobase/row/row0row.c b/innobase/row/row0row.c
index a6d3f1d5ab0..9a74397dc08 100644
--- a/innobase/row/row0row.c
+++ b/innobase/row/row0row.c
@@ -535,7 +535,7 @@ row_build_row_ref_in_tuple(
}
ut_ad(dtuple_check_typed(ref));
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -616,7 +616,6 @@ row_search_on_row_ref(
ulint low_match;
rec_t* rec;
dict_index_t* index;
- page_t* page;
ut_ad(dtuple_check_typed(ref));
@@ -629,9 +628,8 @@ row_search_on_row_ref(
low_match = btr_pcur_get_low_match(pcur);
rec = btr_pcur_get_rec(pcur);
- page = buf_frame_align(rec);
- if (rec == page_get_infimum_rec(page)) {
+ if (page_rec_is_infimum(rec)) {
return(FALSE);
}
@@ -702,7 +700,6 @@ row_search_index_entry(
{
ulint n_fields;
ulint low_match;
- page_t* page;
rec_t* rec;
ut_ad(dtuple_check_typed(entry));
@@ -711,11 +708,10 @@ row_search_index_entry(
low_match = btr_pcur_get_low_match(pcur);
rec = btr_pcur_get_rec(pcur);
- page = buf_frame_align(rec);
n_fields = dtuple_get_n_fields(entry);
- if (rec == page_get_infimum_rec(page)) {
+ if (page_rec_is_infimum(rec)) {
return(FALSE);
}
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 94cf82d6a3d..c7a548fe448 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -125,7 +125,7 @@ row_sel_sec_rec_is_for_clust_rec(
}
func_exit:
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(is_equal);
@@ -630,6 +630,8 @@ row_sel_get_clust_rec(
ulint* offsets = offsets_;
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
+ *out_rec = NULL;
+
offsets = rec_get_offsets(rec,
btr_pcur_get_btr_cur(&plan->pcur)->index,
offsets, ULINT_UNDEFINED, &heap);
@@ -663,8 +665,6 @@ row_sel_get_clust_rec(
clustered index record did not exist in the read view of
trx. */
- clust_rec = NULL;
-
goto func_exit;
}
@@ -733,7 +733,6 @@ row_sel_get_clust_rec(
if ((old_vers || rec_get_deleted_flag(rec, plan->table->comp))
&& !row_sel_sec_rec_is_for_clust_rec(rec, plan->index,
clust_rec, index)) {
- clust_rec = NULL;
goto func_exit;
}
}
@@ -742,11 +741,11 @@ row_sel_get_clust_rec(
row_sel_fetch_columns(index, clust_rec, offsets,
UT_LIST_GET_FIRST(plan->columns));
-func_exit:
*out_rec = clust_rec;
+func_exit:
err = DB_SUCCESS;
err_exit:
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
@@ -1066,7 +1065,7 @@ row_sel_try_search_shortcut(
plan->n_rows_fetched++;
func_exit:
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(SEL_FOUND);
@@ -1261,7 +1260,7 @@ rec_loop:
/* PHASE 1: Set a lock if specified */
if (!node->asc && cursor_just_opened
- && (rec != page_get_supremum_rec(buf_frame_align(rec)))) {
+ && !page_rec_is_supremum(rec)) {
/* When we open a cursor for a descending search, we must set
a next-key lock on the successor record: otherwise it would
@@ -1299,7 +1298,7 @@ rec_loop:
}
}
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
+ if (page_rec_is_infimum(rec)) {
/* The infimum record on a page cannot be in the result set,
and neither can a record lock be placed on it: we skip such
@@ -1337,7 +1336,7 @@ rec_loop:
}
}
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
+ if (page_rec_is_supremum(rec)) {
/* A page supremum record cannot be in the result set: skip
it now when we have placed a possible lock on it */
@@ -1780,7 +1779,7 @@ lock_wait_or_error:
ut_ad(sync_thread_levels_empty_gen(TRUE));
func_exit:
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
@@ -2416,14 +2415,12 @@ row_sel_store_mysql_rec(
mem_heap_t* extern_field_heap = NULL;
byte* data;
ulint len;
- byte* blob_buf;
- int pad_char;
ulint i;
ut_ad(prebuilt->mysql_template);
ut_ad(rec_offs_validate(rec, NULL, offsets));
- if (prebuilt->blob_heap != NULL) {
+ if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
mem_heap_free(prebuilt->blob_heap);
prebuilt->blob_heap = NULL;
}
@@ -2435,7 +2432,8 @@ row_sel_store_mysql_rec(
data = rec_get_nth_field(rec, offsets,
templ->rec_field_no, &len);
- if (rec_offs_nth_extern(offsets, templ->rec_field_no)) {
+ if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
+ templ->rec_field_no))) {
/* Copy an externally stored field to the temporary
heap */
@@ -2456,7 +2454,7 @@ row_sel_store_mysql_rec(
}
if (len != UNIV_SQL_NULL) {
- if (templ->type == DATA_BLOB) {
+ if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
ut_a(prebuilt->templ_contains_blob);
@@ -2465,8 +2463,9 @@ row_sel_store_mysql_rec(
of 1000000 bytes. Since the test takes some
CPU time, we do not use it for small BLOBs. */
- if (len > 2000000
- && !ut_test_malloc(len + 1000000)) {
+ if (UNIV_UNLIKELY(len > 2000000)
+ && UNIV_UNLIKELY(!ut_test_malloc(
+ len + 1000000))) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -2492,11 +2491,9 @@ row_sel_store_mysql_rec(
mem_heap_create(len);
}
- blob_buf = mem_heap_alloc(prebuilt->blob_heap,
- len);
- ut_memcpy(blob_buf, data, len);
-
- data = blob_buf;
+ data = memcpy(mem_heap_alloc(
+ prebuilt->blob_heap, len),
+ data, len);
}
row_sel_field_store_in_mysql_format(
@@ -2521,41 +2518,45 @@ row_sel_store_mysql_rec(
account caused seg faults with NULL BLOB fields, and
bug number 154 in the MySQL bug database: GROUP BY
and DISTINCT could treat NULL values inequal. */
+ int pad_char;
mysql_rec[templ->mysql_null_byte_offset] |=
(byte) (templ->mysql_null_bit_mask);
- if (templ->type == DATA_VARCHAR
- || templ->type == DATA_CHAR
- || templ->type == DATA_BINARY
- || templ->type == DATA_FIXBINARY
- || templ->type == DATA_MYSQL
- || templ->type == DATA_VARMYSQL) {
+ switch (templ->type) {
+ case DATA_VARCHAR:
+ case DATA_CHAR:
+ case DATA_BINARY:
+ case DATA_FIXBINARY:
+ case DATA_MYSQL:
+ case DATA_VARMYSQL:
/* MySQL pads all non-BLOB and non-TEXT
string types with space ' ' */
-
- pad_char = ' ';
- } else {
- pad_char = '\0';
+ if (UNIV_UNLIKELY(templ->mbminlen == 2)) {
+ /* Treat UCS2 as a special case. */
+ data = mysql_rec
+ + templ->mysql_col_offset;
+ len = templ->mysql_col_len;
+ /* There are two UCS2 bytes per char,
+ so the length has to be even. */
+ ut_a(!(len & 1));
+ /* Pad with 0x0020. */
+ while (len) {
+ *data++ = 0x00;
+ *data++ = 0x20;
+ len -= 2;
+ }
+ continue;
+ }
+ pad_char = 0x20;
+ break;
+ default:
+ pad_char = 0x00;
+ break;
}
- /* Handle UCS2 strings differently. */
- if (pad_char != '\0' && templ->mbminlen == 2) {
- /* There are two bytes per char, so the length
- has to be an even number. */
- ut_a(!(templ->mysql_col_len & 1));
- data = mysql_rec + templ->mysql_col_offset;
- len = templ->mysql_col_len;
- /* Pad with 0x0020. */
- while (len >= 2) {
- *data++ = 0x00;
- *data++ = 0x20;
- len -= 2;
- }
- } else {
- ut_ad(!pad_char || templ->mbminlen == 1);
- memset(mysql_rec + templ->mysql_col_offset,
+ ut_ad(!pad_char || templ->mbminlen == 1);
+ memset(mysql_rec + templ->mysql_col_offset,
pad_char, templ->mysql_col_len);
- }
}
}
@@ -2849,8 +2850,9 @@ row_sel_pop_cached_row_for_mysql(
mysql_row_templ_t* templ;
byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0);
+ ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
- if (prebuilt->keep_other_fields_on_keyread)
+ if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread))
{
/* Copy cache record field by field, don't touch fields that
are not covered by current key */
@@ -2877,7 +2879,7 @@ row_sel_pop_cached_row_for_mysql(
else
{
ut_memcpy(buf, prebuilt->fetch_cache[prebuilt->fetch_cache_first],
- prebuilt->mysql_row_len);
+ prebuilt->mysql_prefix_len);
}
prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++;
@@ -2925,9 +2927,9 @@ row_sel_push_cache_row_for_mysql(
ut_ad(prebuilt->fetch_cache_first == 0);
- if (!row_sel_store_mysql_rec(
+ if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
prebuilt->fetch_cache[prebuilt->n_fetch_cached],
- prebuilt, rec, offsets)) {
+ prebuilt, rec, offsets))) {
ut_error;
}
@@ -3048,11 +3050,7 @@ row_search_for_mysql(
rec_t* index_rec;
rec_t* clust_rec;
rec_t* old_vers;
- ulint err = DB_SUCCESS;
- ibool moved;
- ibool cons_read_requires_clust_rec;
- ibool was_lock_wait;
- ulint shortcut;
+ ulint err = DB_SUCCESS;
ibool unique_search = FALSE;
ibool unique_search_from_clust_index = FALSE;
ibool mtr_has_extra_clust_latch = FALSE;
@@ -3062,9 +3060,9 @@ row_search_for_mysql(
locking SELECT, and the isolation
level is <= TRX_ISO_READ_COMMITTED,
then this is set to FALSE */
- ibool success;
- ibool comp;
+#ifdef UNIV_SEARCH_DEBUG
ulint cnt = 0;
+#endif /* UNIV_SEARCH_DEBUG */
ulint next_offs;
mtr_t mtr;
mem_heap_t* heap = NULL;
@@ -3075,7 +3073,7 @@ row_search_for_mysql(
ut_ad(index && pcur && search_tuple);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
- if (prebuilt->table->ibd_file_missing) {
+ if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Error:\n"
"InnoDB: MySQL is trying to use a table handle but the .ibd file for\n"
@@ -3089,7 +3087,7 @@ row_search_for_mysql(
return(DB_ERROR);
}
- if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
+ if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
"InnoDB: table handle. Magic n %lu, table name ",
@@ -3103,7 +3101,7 @@ row_search_for_mysql(
}
if (trx->n_mysql_tables_in_use == 0
- && prebuilt->select_lock_type == LOCK_NONE) {
+ && UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) {
/* Note that if MySQL uses an InnoDB temp table that it
created inside LOCK TABLES, then n_mysql_tables_in_use can
be zero; in that case select_lock_type is set to LOCK_X in
@@ -3126,8 +3124,8 @@ row_search_for_mysql(
/* PHASE 0: Release a possible s-latch we are holding on the
adaptive hash index latch if there is someone waiting behind */
- if (trx->has_search_latch
- && btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
+ if (UNIV_UNLIKELY(btr_search_latch.writer != RW_LOCK_NOT_LOCKED)
+ && trx->has_search_latch) {
/* There is an x-latch request on the adaptive hash index:
release the s-latch to reduce starvation and wait for
@@ -3143,7 +3141,7 @@ row_search_for_mysql(
/*-------------------------------------------------------------*/
/* PHASE 1: Try to pop the row from the prefetch cache */
- if (direction == 0) {
+ if (UNIV_UNLIKELY(direction == 0)) {
trx->op_info = "starting index read";
prebuilt->n_rows_fetched = 0;
@@ -3161,8 +3159,8 @@ row_search_for_mysql(
prebuilt->fetch_direction = direction;
}
- if (direction != prebuilt->fetch_direction) {
- if (prebuilt->n_fetch_cached > 0) {
+ if (UNIV_UNLIKELY(direction != prebuilt->fetch_direction)) {
+ if (UNIV_UNLIKELY(prebuilt->n_fetch_cached > 0)) {
ut_error;
/* TODO: scrollable cursor: restore cursor to
the place of the latest returned row,
@@ -3174,7 +3172,7 @@ row_search_for_mysql(
prebuilt->n_fetch_cached = 0;
prebuilt->fetch_cache_first = 0;
- } else if (prebuilt->n_fetch_cached > 0) {
+ } else if (UNIV_LIKELY(prebuilt->n_fetch_cached > 0)) {
row_sel_pop_cached_row_for_mysql(buf, prebuilt);
prebuilt->n_rows_fetched++;
@@ -3234,7 +3232,8 @@ row_search_for_mysql(
1 column. Return immediately if this is not a HANDLER
command. */
- if (direction != 0 && !prebuilt->used_in_HANDLER) {
+ if (UNIV_UNLIKELY(direction != 0 &&
+ !prebuilt->used_in_HANDLER)) {
err = DB_RECORD_NOT_FOUND;
goto func_exit;
@@ -3252,9 +3251,9 @@ row_search_for_mysql(
cannot use the adaptive hash index in a search in the case the row
may be long and there may be externally stored fields */
- if (unique_search
+ if (UNIV_UNLIKELY(direction == 0)
+ && unique_search
&& index->type & DICT_CLUSTERED
- && direction == 0
&& !prebuilt->templ_contains_blob
&& !prebuilt->used_in_HANDLER
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
@@ -3286,9 +3285,9 @@ row_search_for_mysql(
trx->has_search_latch = TRUE;
}
#endif
- shortcut = row_sel_try_search_shortcut_for_mysql(&rec,
- prebuilt, &offsets, &heap, &mtr);
- if (shortcut == SEL_FOUND) {
+ switch (row_sel_try_search_shortcut_for_mysql(&rec,
+ prebuilt, &offsets, &heap, &mtr)) {
+ case SEL_FOUND:
#ifdef UNIV_SEARCH_DEBUG
ut_a(0 == cmp_dtuple_rec(search_tuple,
rec, offsets));
@@ -3322,9 +3321,8 @@ row_search_for_mysql(
position */
err = DB_SUCCESS;
goto func_exit;
-
- } else if (shortcut == SEL_EXHAUSTED) {
+ case SEL_EXHAUSTED:
mtr_commit(&mtr);
/* ut_print_name(stderr, index->name);
@@ -3367,6 +3365,7 @@ shortcut_fails_too_big_rec:
/* Scan the MySQL query string; check if SELECT is the first
word there */
+ ibool success;
dict_accept(*trx->mysql_query_str, "SELECT", &success);
@@ -3382,7 +3381,7 @@ shortcut_fails_too_big_rec:
naturally moves upward (in fetch next) in alphabetical order,
otherwise downward */
- if (direction == 0) {
+ if (UNIV_UNLIKELY(direction == 0)) {
if (mode == PAGE_CUR_GE || mode == PAGE_CUR_G) {
moves_up = TRUE;
}
@@ -3396,10 +3395,9 @@ shortcut_fails_too_big_rec:
clust_index = dict_table_get_first_index(index->table);
- if (direction != 0) {
- moved = sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
- moves_up, &mtr);
- if (!moved) {
+ if (UNIV_LIKELY(direction != 0)) {
+ if (!sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
+ moves_up, &mtr)) {
goto next_rec;
}
@@ -3440,11 +3438,13 @@ shortcut_fails_too_big_rec:
trx_assign_read_view(trx);
prebuilt->sql_stat_start = FALSE;
} else {
+ ulint lock_mode;
if (prebuilt->select_lock_type == LOCK_S) {
- err = lock_table(0, index->table, LOCK_IS, thr);
+ lock_mode = LOCK_IS;
} else {
- err = lock_table(0, index->table, LOCK_IX, thr);
+ lock_mode = LOCK_IX;
}
+ err = lock_table(0, index->table, lock_mode, thr);
if (err != DB_SUCCESS) {
@@ -3458,8 +3458,8 @@ rec_loop:
/* PHASE 4: Look for matching records in a loop */
rec = btr_pcur_get_rec(pcur);
- comp = index->table->comp;
- ut_ad(comp == page_is_comp(buf_frame_align(rec)));
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
+#ifdef UNIV_SEARCH_DEBUG
/*
fputs("Using ", stderr);
dict_index_name_print(stderr, index);
@@ -3467,7 +3467,9 @@ rec_loop:
buf_frame_get_page_no(buf_frame_align(rec)));
rec_print(rec);
*/
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
+#endif /* UNIV_SEARCH_DEBUG */
+
+ if (page_rec_is_infimum(rec)) {
/* The infimum record on a page cannot be in the result set,
and neither can a record lock be placed on it: we skip such
@@ -3476,10 +3478,11 @@ rec_loop:
goto next_rec;
}
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
+ if (page_rec_is_supremum(rec)) {
- if (prebuilt->select_lock_type != LOCK_NONE
- && set_also_gap_locks) {
+ if (set_also_gap_locks
+ && !srv_locks_unsafe_for_binlog
+ && prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a lock on the index record */
@@ -3487,18 +3490,16 @@ rec_loop:
we do not lock gaps. Supremum record is really
a gap and therefore we do not set locks there. */
- if (!srv_locks_unsafe_for_binlog) {
- offsets = rec_get_offsets(rec, index, offsets,
- ULINT_UNDEFINED, &heap);
- err = sel_set_rec_lock(rec, index, offsets,
- prebuilt->select_lock_type,
- LOCK_ORDINARY, thr);
- if (err != DB_SUCCESS) {
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ err = sel_set_rec_lock(rec, index, offsets,
+ prebuilt->select_lock_type,
+ LOCK_ORDINARY, thr);
- goto lock_wait_or_error;
- }
- }
+ if (err != DB_SUCCESS) {
+ goto lock_wait_or_error;
+ }
}
/* A page supremum record cannot be in the result set: skip
it now that we have placed a possible lock on it */
@@ -3510,12 +3511,19 @@ rec_loop:
/* Do sanity checks in case our cursor has bumped into page
corruption */
- next_offs = rec_get_next_offs(rec, comp);
-
- if (next_offs >= UNIV_PAGE_SIZE
- || next_offs <
- (ulint) (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM)) {
-
+ if (page_rec_is_comp(rec)) {
+ next_offs = rec_get_next_offs(rec, TRUE);
+ if (UNIV_UNLIKELY(next_offs < PAGE_NEW_SUPREMUM)) {
+ goto wrong_offs;
+ }
+ } else {
+ next_offs = rec_get_next_offs(rec, FALSE);
+ if (UNIV_UNLIKELY(next_offs < PAGE_OLD_SUPREMUM)) {
+ goto wrong_offs;
+ }
+ }
+ if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
+ wrong_offs:
if (srv_force_recovery == 0 || moves_up == FALSE) {
ut_print_timestamp(stderr);
buf_page_print(buf_frame_align(rec));
@@ -3528,7 +3536,7 @@ rec_loop:
fprintf(stderr,
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: ",
- (ulong) (rec - buf_frame_align(rec)),
+ (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE),
(ulong) next_offs,
(ulong) buf_frame_get_page_no(rec));
dict_index_name_print(stderr, trx, index);
@@ -3546,7 +3554,7 @@ rec_loop:
fprintf(stderr,
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: ",
- (ulong) (rec - buf_frame_align(rec)),
+ (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE),
(ulong) next_offs,
(ulong) buf_frame_get_page_no(rec));
dict_index_name_print(stderr, trx, index);
@@ -3561,13 +3569,13 @@ rec_loop:
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
- if (srv_force_recovery > 0) {
+ if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
if (!rec_validate(rec, offsets)
|| !btr_index_rec_validate(rec, index, FALSE)) {
fprintf(stderr,
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: ",
- (ulong) (rec - buf_frame_align(rec)),
+ (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE),
(ulong) next_offs,
(ulong) buf_frame_get_page_no(rec));
dict_index_name_print(stderr, trx, index);
@@ -3593,25 +3601,22 @@ rec_loop:
if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) {
- if (prebuilt->select_lock_type != LOCK_NONE
- && set_also_gap_locks) {
+ if (set_also_gap_locks
+ && !srv_locks_unsafe_for_binlog
+ && prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a gap lock on the index
record only if innodb_locks_unsafe_for_binlog
option is not set */
- if (srv_locks_unsafe_for_binlog == FALSE) {
-
- err = sel_set_rec_lock(rec, index,
- offsets,
+ err = sel_set_rec_lock(rec, index, offsets,
prebuilt->select_lock_type,
LOCK_GAP, thr);
- if (err != DB_SUCCESS) {
- goto lock_wait_or_error;
- }
- }
+ if (err != DB_SUCCESS) {
+ goto lock_wait_or_error;
+ }
}
btr_pcur_store_position(pcur, &mtr);
@@ -3627,25 +3632,22 @@ rec_loop:
if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) {
- if (prebuilt->select_lock_type != LOCK_NONE
- && set_also_gap_locks) {
+ if (set_also_gap_locks
+ && !srv_locks_unsafe_for_binlog
+ && prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a gap lock on the index
record only if innodb_locks_unsafe_for_binlog
option is not set */
- if (srv_locks_unsafe_for_binlog == FALSE) {
-
- err = sel_set_rec_lock(rec, index,
- offsets,
+ err = sel_set_rec_lock(rec, index, offsets,
prebuilt->select_lock_type,
LOCK_GAP, thr);
- if (err != DB_SUCCESS) {
- goto lock_wait_or_error;
- }
- }
+ if (err != DB_SUCCESS) {
+ goto lock_wait_or_error;
+ }
}
btr_pcur_store_position(pcur, &mtr);
@@ -3661,29 +3663,25 @@ rec_loop:
/* We are ready to look at a possible new index entry in the result
set: the cursor is now placed on a user record */
- cons_read_requires_clust_rec = FALSE;
-
if (prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a lock on the index record; note that delete
marked records are a special case in a unique search. If there
is a non-delete marked record, then it is enough to lock its
existence with LOCK_REC_NOT_GAP. */
+ /* If innodb_locks_unsafe_for_binlog option is used,
+ we lock only the record, i.e., next-key locking is
+ not used. */
+
ulint lock_type;
if (!set_also_gap_locks
- || (unique_search && !rec_get_deleted_flag(rec, comp))) {
- lock_type = LOCK_REC_NOT_GAP;
+ || srv_locks_unsafe_for_binlog
+ || (unique_search && !UNIV_UNLIKELY(rec_get_deleted_flag(
+ rec, page_rec_is_comp(rec))))) {
+ goto no_gap_lock;
} else {
- /* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e., next-key locking is
- not used. */
-
- if (srv_locks_unsafe_for_binlog) {
- lock_type = LOCK_REC_NOT_GAP;
- } else {
- lock_type = LOCK_ORDINARY;
- }
+ lock_type = LOCK_ORDINARY;
}
/* If we are doing a 'greater or equal than a primary key
@@ -3703,7 +3701,7 @@ rec_loop:
&& dtuple_get_n_fields_cmp(search_tuple)
== dict_index_get_n_unique(index)
&& 0 == cmp_dtuple_rec(search_tuple, rec, offsets)) {
-
+ no_gap_lock:
lock_type = LOCK_REC_NOT_GAP;
}
@@ -3731,7 +3729,7 @@ rec_loop:
high force recovery level set, we try to avoid crashes
by skipping this lookup */
- if (srv_force_recovery < 5
+ if (UNIV_LIKELY(srv_force_recovery < 5)
&& !lock_clust_rec_cons_read_sees(rec, index,
offsets, trx->read_view)) {
@@ -3762,13 +3760,15 @@ rec_loop:
have to look also into the clustered index: this
is necessary, because we can only get the undo
information via the clustered index record. */
-
- cons_read_requires_clust_rec = TRUE;
+
+ /* Get the clustered index record if needed */
+ index_rec = rec;
+ ut_ad(index != clust_index);
+ goto requires_clust_rec;
}
}
- if (rec_get_deleted_flag(rec, comp)
- && !cons_read_requires_clust_rec) {
+ if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, page_rec_is_comp(rec)))) {
/* The record is delete-marked: we can skip it if this is
not a consistent read which might see an earlier version
@@ -3782,14 +3782,14 @@ rec_loop:
index_rec = rec;
- /* Before and after the following "if" block, "offsets" will be
- related to "rec", which may be in "index", a secondary index or
- the clustered index ("clust_index"). However, after this "if" block,
- "rec" may be pointing to "clust_rec" of "clust_index". */
- ut_ad(rec_offs_validate(rec, index, offsets));
-
- if (index != clust_index && (cons_read_requires_clust_rec
- || prebuilt->need_to_access_clustered)) {
+ if (index != clust_index && prebuilt->need_to_access_clustered) {
+ requires_clust_rec:
+ /* Before and after this "if" block, "offsets" will be
+ related to "rec", which may be in a secondary index "index" or
+ the clustered index ("clust_index"). However, after this
+ "if" block, "rec" may be pointing to
+ "clust_rec" of "clust_index". */
+ ut_ad(rec_offs_validate(rec, index, offsets));
/* It was a non-clustered index and we must fetch also the
clustered index record */
@@ -3811,7 +3811,8 @@ rec_loop:
goto next_rec;
}
- if (rec_get_deleted_flag(clust_rec, comp)) {
+ if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec,
+ page_rec_is_comp(clust_rec)))) {
/* The record is delete marked: we can skip it */
@@ -3832,7 +3833,8 @@ rec_loop:
rec == clust_rec ? clust_index : index,
offsets));
- if (prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD
+ if ((match_mode == ROW_SEL_EXACT
+ || prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD)
&& prebuilt->select_lock_type == LOCK_NONE
&& !prebuilt->templ_contains_blob
&& !prebuilt->clust_index_was_generated
@@ -3907,7 +3909,7 @@ next_rec:
/*-------------------------------------------------------------*/
/* PHASE 5: Move the cursor to the next index record */
- if (mtr_has_extra_clust_latch) {
+ if (UNIV_UNLIKELY(mtr_has_extra_clust_latch)) {
/* We must commit mtr if we are moving to the next
non-clustered index record, because we could break the
latching order if we would access a different clustered
@@ -3919,34 +3921,38 @@ next_rec:
mtr_has_extra_clust_latch = FALSE;
mtr_start(&mtr);
- moved = sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
- moves_up, &mtr);
- if (moved) {
+ if (sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
+ moves_up, &mtr)) {
+#ifdef UNIV_SEARCH_DEBUG
cnt++;
+#endif /* UNIV_SEARCH_DEBUG */
goto rec_loop;
}
}
if (moves_up) {
- moved = btr_pcur_move_to_next(pcur, &mtr);
- } else {
- moved = btr_pcur_move_to_prev(pcur, &mtr);
- }
+ if (UNIV_UNLIKELY(!btr_pcur_move_to_next(pcur, &mtr))) {
+ not_moved:
+ btr_pcur_store_position(pcur, &mtr);
- if (!moved) {
- btr_pcur_store_position(pcur, &mtr);
+ if (match_mode != 0) {
+ err = DB_RECORD_NOT_FOUND;
+ } else {
+ err = DB_END_OF_INDEX;
+ }
- if (match_mode != 0) {
- err = DB_RECORD_NOT_FOUND;
- } else {
- err = DB_END_OF_INDEX;
+ goto normal_return;
+ }
+ } else {
+ if (UNIV_UNLIKELY(!btr_pcur_move_to_prev(pcur, &mtr))) {
+ goto not_moved;
}
-
- goto normal_return;
}
+#ifdef UNIV_SEARCH_DEBUG
cnt++;
+#endif /* UNIV_SEARCH_DEBUG */
goto rec_loop;
@@ -3964,11 +3970,10 @@ lock_wait_or_error:
que_thr_stop_for_mysql(thr);
- thr->lock_state= QUE_THR_LOCK_ROW;
- was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
- thr->lock_state= QUE_THR_LOCK_NOLOCK;
+ thr->lock_state = QUE_THR_LOCK_ROW;
- if (was_lock_wait) {
+ if (row_mysql_handle_errors(&err, trx, thr, NULL)) {
+ thr->lock_state = QUE_THR_LOCK_NOLOCK;
mtr_start(&mtr);
sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
@@ -3978,9 +3983,13 @@ lock_wait_or_error:
goto rec_loop;
}
+ thr->lock_state = QUE_THR_LOCK_NOLOCK;
+
+#ifdef UNIV_SEARCH_DEBUG
/* fputs("Using ", stderr);
dict_index_name_print(stderr, index);
fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
+#endif /* UNIV_SEARCH_DEBUG */
goto func_exit;
normal_return:
@@ -3995,16 +4004,18 @@ normal_return:
err = DB_SUCCESS;
}
+#ifdef UNIV_SEARCH_DEBUG
/* fputs("Using ", stderr);
dict_index_name_print(stderr, index);
fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
+#endif /* UNIV_SEARCH_DEBUG */
if (err == DB_SUCCESS) {
srv_n_rows_read++;
}
func_exit:
trx->op_info = "";
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c
index 1cade0f304f..0225a9faec5 100644
--- a/innobase/row/row0umod.c
+++ b/innobase/row/row0umod.c
@@ -52,19 +52,16 @@ row_undo_mod_undo_also_prev_vers(
/* out: TRUE if also previous modify or
insert of this row should be undone */
undo_node_t* node, /* in: row undo node */
- que_thr_t* thr, /* in: query thread */
dulint* undo_no)/* out: the undo number */
{
trx_undo_rec_t* undo_rec;
- ibool ret;
trx_t* trx;
- UT_NOT_USED(thr);
-
trx = node->trx;
if (0 != ut_dulint_cmp(node->new_trx_id, trx->id)) {
+ *undo_no = ut_dulint_zero;
return(FALSE);
}
@@ -72,13 +69,7 @@ row_undo_mod_undo_also_prev_vers(
*undo_no = trx_undo_rec_get_undo_no(undo_rec);
- if (ut_dulint_cmp(trx->roll_limit, *undo_no) <= 0) {
- ret = TRUE;
- } else {
- ret = FALSE;
- }
-
- return(ret);
+ return(ut_dulint_cmp(trx->roll_limit, *undo_no) <= 0);
}
/***************************************************************
@@ -214,7 +205,7 @@ row_undo_mod_clust(
/* Check if also the previous version of the clustered index record
should be undone in this same rollback operation */
- more_vers = row_undo_mod_undo_also_prev_vers(node, thr, &new_undo_no);
+ more_vers = row_undo_mod_undo_also_prev_vers(node, &new_undo_no);
pcur = &(node->pcur);
diff --git a/innobase/row/row0undo.c b/innobase/row/row0undo.c
index abe73cbe705..435c0279dbb 100644
--- a/innobase/row/row0undo.c
+++ b/innobase/row/row0undo.c
@@ -190,7 +190,7 @@ row_undo_search_clust_to_pcur(
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(ret);
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index 3305724a89b..514fb6bd577 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -815,9 +815,10 @@ row_upd_build_difference_binary(
goto skip_compare;
}
- extern_bit = rec_offs_nth_extern(offsets, i);
+ extern_bit = upd_ext_vec_contains(ext_vec, n_ext_vec, i);
- if (extern_bit != upd_ext_vec_contains(ext_vec, n_ext_vec, i)
+ if (UNIV_UNLIKELY(extern_bit ==
+ (ibool)!rec_offs_nth_extern(offsets, i))
|| !dfield_data_is_binary_equal(dfield, len, data)) {
upd_field = upd_get_nth_field(update, n_diff);
@@ -826,12 +827,8 @@ row_upd_build_difference_binary(
upd_field_set_field_no(upd_field, i, index, trx);
- if (upd_ext_vec_contains(ext_vec, n_ext_vec, i)) {
- upd_field->extern_storage = TRUE;
- } else {
- upd_field->extern_storage = FALSE;
- }
-
+ upd_field->extern_storage = extern_bit;
+
n_diff++;
}
skip_compare:
@@ -1224,7 +1221,7 @@ row_upd_store_row(
node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec,
offsets, update);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@@ -1270,7 +1267,7 @@ row_upd_sec_index_entry(
rec = btr_cur_get_rec(btr_cur);
- if (!found) {
+ if (UNIV_UNLIKELY(!found)) {
fputs("InnoDB: error in sec index entry update in\n"
"InnoDB: ", stderr);
dict_index_name_print(stderr, trx, index);
@@ -1423,7 +1420,7 @@ row_upd_clust_rec_by_insert(
index, thr, mtr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
@@ -1549,7 +1546,7 @@ row_upd_clust_rec(
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
big_rec, mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
mtr_commit(mtr);
@@ -1719,7 +1716,7 @@ row_upd_clust_step(
node->index = dict_table_get_next_index(index);
}
exit_func:
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
@@ -1736,7 +1733,7 @@ row_upd_clust_step(
row_upd_eval_new_vals(node->update);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -2016,7 +2013,7 @@ row_upd_in_place_in_select(
btr_pcur_get_rec(pcur), btr_cur->index, offsets_,
ULINT_UNDEFINED, &heap),
UT_LIST_GET_FIRST(node->columns));
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
row_upd_eval_new_vals(node->update);
diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c
index 36f6c27636d..8e747423047 100644
--- a/innobase/row/row0vers.c
+++ b/innobase/row/row0vers.c
@@ -57,11 +57,11 @@ row_vers_impl_x_locked_off_kernel(
dtuple_t* entry = NULL; /* assignment to eliminate compiler
warning */
trx_t* trx;
- ibool vers_del;
- ibool rec_del;
+ ulint vers_del;
+ ulint rec_del;
ulint err;
mtr_t mtr;
- ibool comp;
+ ulint comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -121,10 +121,10 @@ row_vers_impl_x_locked_off_kernel(
goto exit_func;
}
- comp = index->table->comp;
+ comp = page_rec_is_comp(rec);
ut_ad(index->table == clust_index->table);
- ut_ad(comp == page_is_comp(buf_frame_align(rec)));
- ut_ad(comp == page_is_comp(buf_frame_align(clust_rec)));
+ ut_ad(!!comp == index->table->comp);
+ ut_ad(!comp == !page_rec_is_comp(clust_rec));
/* We look up if some earlier version, which was modified by the trx_id
transaction, of the clustered index record would require rec to be in
@@ -310,7 +310,7 @@ row_vers_old_has_index_entry(
dtuple_t* row;
dtuple_t* entry;
ulint err;
- ibool comp;
+ ulint comp;
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains(mtr, buf_block_align(rec),
@@ -322,8 +322,8 @@ row_vers_old_has_index_entry(
clust_index = dict_table_get_first_index(index->table);
- comp = index->table->comp;
- ut_ad(comp == page_is_comp(buf_frame_align(rec)));
+ comp = page_rec_is_comp(rec);
+ ut_ad(!index->table->comp == !comp);
heap = mem_heap_create(1024);
clust_offsets = rec_get_offsets(rec, clust_index, NULL,
ULINT_UNDEFINED, &heap);
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 541b73b831d..7798e0c8e32 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1040,7 +1040,9 @@ innobase_start_or_create_for_mysql(void)
srv_start_has_been_called = TRUE;
+#ifdef UNIV_DEBUG
log_do_write = TRUE;
+#endif /* UNIV_DEBUG */
/* yydebug = TRUE; */
srv_is_being_started = TRUE;
@@ -1554,8 +1556,9 @@ NetWare. */
os_thread_create(&srv_master_thread, NULL, thread_ids + 1 +
SRV_MAX_N_IO_THREADS);
+#ifdef UNIV_DEBUG
/* buf_debug_prints = TRUE; */
-
+#endif /* UNIV_DEBUG */
sum_of_data_file_sizes = 0;
for (i = 0; i < srv_n_data_files; i++) {
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index e604912e996..f0f0e9a3a2e 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -1136,8 +1136,12 @@ sync_thread_add_level(
} else if (level == SYNC_DICT_HEADER) {
ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER));
} else if (level == SYNC_DICT) {
+#ifdef UNIV_DEBUG
ut_a(buf_debug_prints
|| sync_thread_levels_g(array, SYNC_DICT));
+#else /* UNIV_DEBUG */
+ ut_a(sync_thread_levels_g(array, SYNC_DICT));
+#endif /* UNIV_DEBUG */
} else {
ut_error;
}
diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c
index fcb7582ce73..3b7171e6038 100644
--- a/innobase/trx/trx0rec.c
+++ b/innobase/trx/trx0rec.c
@@ -941,13 +941,11 @@ trx_undo_erase_page_end(
mtr_t* mtr) /* in: mtr */
{
ulint first_free;
- ulint i;
-
+
first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_FREE);
- for (i = first_free; i < UNIV_PAGE_SIZE - FIL_PAGE_DATA_END; i++) {
- undo_page[i] = 0xFF;
- }
+ memset(undo_page + first_free, 0xff,
+ (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END) - first_free);
mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr);
}
@@ -1134,7 +1132,7 @@ trx_undo_report_row_operation(
mutex_exit(&(trx->undo_mutex));
mtr_commit(&mtr);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(DB_OUT_OF_FILE_SPACE);
@@ -1153,7 +1151,7 @@ trx_undo_report_row_operation(
*roll_ptr = trx_undo_build_roll_ptr(is_insert, rseg->id, page_no,
offset);
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(DB_SUCCESS);
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index 69f7a99187f..fdfb7428129 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -1237,10 +1237,12 @@ trx_finish_rollback_off_kernel(
return;
}
+#ifdef UNIV_DEBUG
if (lock_print_waits) {
fprintf(stderr, "Trx %lu rollback finished\n",
(ulong) ut_dulint_get_low(trx->id));
}
+#endif /* UNIV_DEBUG */
trx_commit_off_kernel(trx);
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index c6d1f953772..9e155ee1de0 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -158,8 +158,6 @@ trx_create(
trx->n_tickets_to_enter_innodb = 0;
trx->auto_inc_lock = NULL;
- trx->n_lock_table_exp = 0;
- trx->n_lock_table_transactional = 0;
trx->read_view_heap = mem_heap_create(256);
trx->read_view = NULL;
@@ -309,8 +307,6 @@ trx_free(
ut_a(!trx->has_search_latch);
ut_a(!trx->auto_inc_lock);
- ut_a(!trx->n_lock_table_exp);
- ut_a(!trx->n_lock_table_transactional);
ut_a(trx->dict_operation_lock_mode == 0);
@@ -1711,12 +1707,6 @@ trx_print(
(ulong) trx->mysql_n_tables_locked);
}
- if (trx->n_lock_table_transactional > 0 || trx->n_lock_table_exp > 0) {
-fprintf(f, "mysql explicit table locks %lu, transactional table locks %lu\n",
- (ulong) trx->n_lock_table_exp,
- (ulong) trx->n_lock_table_transactional);
- }
-
newline = TRUE;
switch (trx->que_state) {
diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c
index bb314dd35e9..7441dd3f152 100644
--- a/innobase/trx/trx0undo.c
+++ b/innobase/trx/trx0undo.c
@@ -556,19 +556,19 @@ void
trx_undo_write_xid(
/*===============*/
trx_ulogf_t* log_hdr,/* in: undo log header */
- XID* xid, /* in: X/Open XA Transaction Identification */
+ const XID* xid, /* in: X/Open XA Transaction Identification */
mtr_t* mtr) /* in: mtr */
{
- mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT, xid->formatID,
- MLOG_4BYTES, mtr);
+ mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT,
+ (ulint)xid->formatID, MLOG_4BYTES, mtr);
- mlog_write_ulint(log_hdr + TRX_UNDO_XA_TRID_LEN, xid->gtrid_length,
- MLOG_4BYTES, mtr);
+ mlog_write_ulint(log_hdr + TRX_UNDO_XA_TRID_LEN,
+ (ulint)xid->gtrid_length, MLOG_4BYTES, mtr);
- mlog_write_ulint(log_hdr + TRX_UNDO_XA_BQUAL_LEN, xid->bqual_length,
- MLOG_4BYTES, mtr);
+ mlog_write_ulint(log_hdr + TRX_UNDO_XA_BQUAL_LEN,
+ (ulint)xid->bqual_length, MLOG_4BYTES, mtr);
- mlog_write_string(log_hdr + TRX_UNDO_XA_XID, xid->data,
+ mlog_write_string(log_hdr + TRX_UNDO_XA_XID, (const byte*) xid->data,
XIDDATASIZE, mtr);
}
@@ -581,18 +581,14 @@ trx_undo_read_xid(
trx_ulogf_t* log_hdr,/* in: undo log header */
XID* xid) /* out: X/Open XA Transaction Identification */
{
- ulint i;
-
- xid->formatID = mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT);
+ xid->formatID = (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT);
- xid->gtrid_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN);
-
- xid->bqual_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN);
+ xid->gtrid_length =
+ (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN);
+ xid->bqual_length =
+ (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN);
- for (i = 0; i < XIDDATASIZE; i++) {
- xid->data[i] = (char)mach_read_from_1(log_hdr +
- TRX_UNDO_XA_XID + i);
- }
+ memcpy(xid->data, log_hdr + TRX_UNDO_XA_XID, XIDDATASIZE);
}
/*******************************************************************
diff --git a/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c
index 0f6a27d35d9..e810d8dead7 100644
--- a/innobase/ut/ut0dbg.c
+++ b/innobase/ut/ut0dbg.c
@@ -8,8 +8,11 @@ Created 1/30/1994 Heikki Tuuri
#include "univ.i"
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#else
/* This is used to eliminate compiler warnings */
ulint ut_dbg_zero = 0;
+#endif
/* If this is set to TRUE all threads will stop into the next assertion
and assert */
@@ -19,21 +22,69 @@ ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there
happens an InnoDB assertion failure or other
fatal error condition that requires an
immediate shutdown. */
-#endif
+#else /* __NETWARE__ */
/* Null pointer used to generate memory trap */
ulint* ut_dbg_null_ptr = NULL;
+#endif /* __NETWARE__ */
+
+/*****************************************************************
+Report a failed assertion. */
-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 =
+void
+ut_dbg_assertion_failed(
+/*====================*/
+ const char* expr, /* in: the failed assertion (optional) */
+ const char* file, /* in: source file containing the assertion */
+ ulint line) /* in: line number of the assertion */
+{
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ "InnoDB: Assertion failure in thread %lu"
+ " in file %s line %lu\n",
+ os_thread_pf(os_thread_get_curr_id()), file, line);
+ if (expr) {
+ fprintf(stderr,
+ "InnoDB: Failing assertion: %s\n", expr);
+ }
+
+ fputs(
"InnoDB: We intentionally generate a memory trap.\n"
"InnoDB: Submit a detailed bug report to http://bugs.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. Please refer to\n"
"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n"
-"InnoDB: about forcing recovery.\n";
+"InnoDB: about forcing recovery.\n", stderr);
+ ut_dbg_stop_threads = TRUE;
+}
+
+#ifdef __NETWARE__
+/*****************************************************************
+Shut down MySQL/InnoDB after assertion failure. */
+
+void
+ut_dbg_panic(void)
+/*==============*/
+{
+ if (!panic_shutdown) {
+ panic_shutdown = TRUE;
+ innobase_shutdown_for_mysql();
+ }
+ exit(1);
+}
+#else /* __NETWARE__ */
+/*****************************************************************
+Stop a thread after assertion failure. */
-const char* ut_dbg_msg_stop =
-"InnoDB: Thread %lu stopped in file %s line %lu\n";
+void
+ut_dbg_stop_thread(
+/*===============*/
+ const char* file,
+ ulint line)
+{
+ fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n",
+ os_thread_pf(os_thread_get_curr_id()), file, line);
+ os_thread_sleep(1000000000);
+}
+#endif /* __NETWARE__ */
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 753657951ee..8ee11519615 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1736,7 +1736,7 @@ myodbc_remove_escape(MYSQL *mysql,char *name)
/******************* Declarations ***********************************/
-/* Default number of rows fetched per one COM_FETCH command. */
+/* Default number of rows fetched per one COM_STMT_FETCH command. */
#define DEFAULT_PREFETCH_ROWS (ulong) 1
@@ -1887,7 +1887,7 @@ void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode,
}
/*
- Read and unpack server reply to COM_PREPARE command (sent from
+ Read and unpack server reply to COM_STMT_PREPARE command (sent from
mysql_stmt_prepare).
SYNOPSIS
@@ -2082,7 +2082,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
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))
+ if (simple_command(mysql, COM_STMT_CLOSE, buff, 4, 1))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
@@ -2091,7 +2091,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
stmt->state= MYSQL_STMT_INIT_DONE;
}
- if (simple_command(mysql, COM_PREPARE, query, length, 1))
+ if (simple_command(mysql, COM_STMT_PREPARE, query, length, 1))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
@@ -2175,7 +2175,7 @@ static unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
/*
Update result set columns metadata if it was sent again in
- reply to COM_EXECUTE.
+ reply to COM_STMT_EXECUTE.
*/
static void update_stmt_fields(MYSQL_STMT *stmt)
@@ -2490,7 +2490,7 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
/*
- Auxilary function to send COM_EXECUTE packet to server and read reply.
+ Auxilary function to send COM_STMT_EXECUTE packet to server and read reply.
Used from cli_stmt_execute, which is in turn used by mysql_stmt_execute.
*/
@@ -2507,7 +2507,7 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
buff[4]= (char) stmt->flags;
int4store(buff+5, 1); /* iteration count */
- if (cli_advanced_command(mysql, COM_EXECUTE, buff, sizeof(buff),
+ if (cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff),
packet, length, 1) ||
(*mysql->methods->read_query_result)(mysql))
{
@@ -2720,7 +2720,7 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row)
/* Send row request to the server */
int4store(buff, stmt->stmt_id);
int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
- if (cli_advanced_command(mysql, COM_FETCH, buff, sizeof(buff),
+ if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
NullS, 0, 1))
{
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
@@ -2910,7 +2910,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
- if data dictionary changed between prepare and execute, for
example a table used in the query was altered.
Note, that now (4.1.3) we always send metadata in reply to
- COM_EXECUTE (even if it is not necessary), so either this or
+ COM_STMT_EXECUTE (even if it is not necessary), so either this or
previous branch always works.
TODO: send metadata only when it's really necessary and add a warning
'Metadata changed' when it's sent twice.
@@ -3380,8 +3380,9 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
Note that we don't get any ok packet from the server in this case
This is intentional to save bandwidth.
*/
- if ((*mysql->methods->advanced_command)(mysql, COM_LONG_DATA, buff,
- sizeof(buff), data, length, 1))
+ if ((*mysql->methods->advanced_command)(mysql, COM_STMT_SEND_LONG_DATA,
+ buff, sizeof(buff), data,
+ length, 1))
{
set_stmt_errmsg(stmt, mysql->net.last_error,
mysql->net.last_errno, mysql->net.sqlstate);
@@ -4930,7 +4931,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
*/
char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
int4store(buff, stmt->stmt_id);
- if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff,
+ if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff,
sizeof(buff), 0, 0, 0))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
@@ -5004,7 +5005,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
mysql->status= MYSQL_STATUS_READY;
}
int4store(buff, stmt->stmt_id);
- if ((rc= simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1)))
+ if ((rc= simple_command(mysql, COM_STMT_CLOSE, buff, 4, 1)))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 74a1c8c7922..dd4ba939ebe 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -220,7 +220,7 @@ static int emb_stmt_execute(MYSQL_STMT *stmt)
THD *thd= (THD*)stmt->mysql->thd;
thd->client_param_count= stmt->param_count;
thd->client_params= stmt->params;
- if (emb_advanced_command(stmt->mysql, COM_EXECUTE,0,0,
+ if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0,
header, sizeof(header), 1) ||
emb_mysql_read_query_result(stmt->mysql))
{
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 530f0d56c4c..35c41b7d2d6 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -410,7 +410,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
Hack: instead of init_queue, we'll use reinit queue to be able
to alloc queue with alloc_root()
*/
- res=ftb->queue.max_elements=1+query_len/(min(ft_min_word_len,2)+1);
+ res=ftb->queue.max_elements=1+query_len/2;
if (!(ftb->queue.root=
(byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*))))
goto err;
diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c
index 4b512dd89dd..c251e4dda4a 100644
--- a/myisam/mi_packrec.c
+++ b/myisam/mi_packrec.c
@@ -416,8 +416,19 @@ static uint find_longest_bitstream(uint16 *table, uint16 *end)
}
- /* Read record from datafile */
- /* Returns length of packed record, -1 if error */
+/*
+ Read record from datafile.
+
+ SYNOPSIS
+ _mi_read_pack_record()
+ info A pointer to MI_INFO.
+ filepos File offset of the record.
+ buf RETURN The buffer to receive the record.
+
+ RETURN
+ 0 on success
+ HA_ERR_WRONG_IN_RECORD or -1 on error
+*/
int _mi_read_pack_record(MI_INFO *info, my_off_t filepos, byte *buf)
{
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 74bb541b220..70a32902da6 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -33,10 +33,10 @@
#include <my_getopt.h>
#include <assert.h>
-#if INT_MAX > 32767
-#define BITS_SAVED 32
+#if SIZEOF_LONG_LONG > 4
+#define BITS_SAVED 64
#else
-#define BITS_SAVED 16
+#define BITS_SAVED 32
#endif
#define IS_OFFSET ((uint) 32768) /* Bit if offset or char in tree */
@@ -49,10 +49,10 @@
struct st_file_buffer {
File file;
- char *buffer,*pos,*end;
+ uchar *buffer,*pos,*end;
my_off_t pos_in_file;
int bits;
- uint current_byte;
+ ulonglong bitbucket;
};
struct st_huff_tree;
@@ -69,13 +69,17 @@ typedef struct st_huff_counts {
my_off_t end_space[8];
my_off_t pre_space[8];
my_off_t tot_end_space,tot_pre_space,zero_fields,empty_fields,bytes_packed;
- TREE int_tree;
- byte *tree_buff;
- byte *tree_pos;
+ TREE int_tree; /* Tree for detecting distinct column values. */
+ byte *tree_buff; /* Column values, 'field_length' each. */
+ byte *tree_pos; /* Points to end of column values in 'tree_buff'. */
} HUFF_COUNTS;
typedef struct st_huff_element HUFF_ELEMENT;
+/*
+ WARNING: It is crucial for the optimizations in calc_packed_length()
+ that 'count' is the first element of 'HUFF_ELEMENT'.
+*/
struct st_huff_element {
my_off_t count;
union un_element {
@@ -98,7 +102,7 @@ typedef struct st_huff_tree {
my_off_t bytes_packed;
uint tree_pack_length;
uint min_chr,max_chr,char_bits,offset_bits,max_offset,height;
- ulong *code;
+ ulonglong *code;
uchar *code_len;
} HUFF_TREE;
@@ -146,7 +150,7 @@ static uint join_same_trees(HUFF_COUNTS *huff_counts,uint trees);
static int make_huff_decode_table(HUFF_TREE *huff_tree,uint trees);
static void make_traverse_code_tree(HUFF_TREE *huff_tree,
HUFF_ELEMENT *element,uint size,
- ulong code);
+ ulonglong code);
static int write_header(PACK_MRG_INFO *isam_file, uint header_length,uint trees,
my_off_t tot_elements,my_off_t filelength);
static void write_field_info(HUFF_COUNTS *counts, uint fields,uint trees);
@@ -161,7 +165,7 @@ static char *make_old_name(char *new_name,char *old_name);
static void init_file_buffer(File file,pbool read_buffer);
static int flush_buffer(ulong neaded_length);
static void end_file_buffer(void);
-static void write_bits(ulong value,uint bits);
+static void write_bits(ulonglong value, uint bits);
static void flush_bits(void);
static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
ha_checksum crc);
@@ -170,13 +174,23 @@ static int save_state_mrg(File file,PACK_MRG_INFO *isam_file,my_off_t new_length
static int mrg_close(PACK_MRG_INFO *mrg);
static int mrg_rrnd(PACK_MRG_INFO *info,byte *buf);
static void mrg_reset(PACK_MRG_INFO *mrg);
+#if !defined(DBUG_OFF)
+static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count);
+static int fakecmp(my_off_t **count1, my_off_t **count2);
+#endif
static int error_on_write=0,test_only=0,verbose=0,silent=0,
write_loop=0,force_pack=0, isamchk_neaded=0;
static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
static my_bool backup, opt_wait;
-static uint tree_buff_length=8196-MALLOC_OVERHEAD;
+/*
+ tree_buff_length is somewhat arbitrary. The bigger it is the better
+ the chance to win in terms of compression factor. On the other hand,
+ this table becomes part of the compressed file header. And its length
+ is coded with 16 bits in the header. Hence the limit is 2**16 - 1.
+*/
+static uint tree_buff_length= 65536 - MALLOC_OVERHEAD;
static char tmp_dir[FN_REFLEN]={0},*join_table;
static my_off_t intervall_length;
static ha_checksum glob_crc;
@@ -225,7 +239,8 @@ int main(int argc, char **argv)
}
if (ok && isamchk_neaded && !silent)
puts("Remember to run myisamchk -rq on compressed tables");
- VOID(fflush(stdout)); VOID(fflush(stderr));
+ VOID(fflush(stdout));
+ VOID(fflush(stderr));
free_defaults(default_argv);
my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
exit(error ? 2 : 0);
@@ -260,7 +275,7 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"test", 't', "Don't pack table, only test packing it.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"verbose", 'v', "Write info about progress and packing result.",
+ {"verbose", 'v', "Write info about progress and packing result. Use many -v for more verbosity!",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -273,7 +288,8 @@ static struct my_option my_long_options[] =
static void print_version(void)
{
- printf("%s Ver 1.22 for %s on %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
+ VOID(printf("%s Ver 1.22 for %s on %s\n",
+ my_progname, SYSTEM_TYPE, MACHINE_TYPE));
NETWARE_SET_SCREEN_MODE(1);
}
@@ -290,7 +306,7 @@ static void usage(void)
puts("afterwards to update the keys.");
puts("You should give the .MYI file as the filename argument.");
- printf("\nUsage: %s [OPTIONS] filename...\n", my_progname);
+ VOID(printf("\nUsage: %s [OPTIONS] filename...\n", my_progname));
my_print_help(my_long_options);
print_defaults("my", load_default_groups);
my_print_variables(my_long_options);
@@ -314,7 +330,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
silent= 1;
break;
case 't':
- test_only= verbose= 1;
+ test_only= 1;
+ /* Avoid to reset 'verbose' if it was already set > 1. */
+ if (! verbose)
+ verbose= 1;
break;
case 'T':
length= (uint) (strmov(tmp_dir, argument) - tmp_dir);
@@ -325,7 +344,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
break;
case 'v':
- verbose= 1;
+ verbose++; /* Allow for selecting the level of verbosity. */
silent= 0;
break;
case '#':
@@ -380,7 +399,7 @@ static MI_INFO *open_isam_file(char *name,int mode)
(opt_wait ? HA_OPEN_WAIT_IF_LOCKED :
HA_OPEN_ABORT_IF_LOCKED))))
{
- VOID(fprintf(stderr,"%s gave error %d on open\n",name,my_errno));
+ VOID(fprintf(stderr, "%s gave error %d on open\n", name, my_errno));
DBUG_RETURN(0);
}
share=isam_file->s;
@@ -388,7 +407,7 @@ static MI_INFO *open_isam_file(char *name,int mode)
{
if (!force_pack)
{
- VOID(fprintf(stderr,"%s is already compressed\n",name));
+ VOID(fprintf(stderr, "%s is already compressed\n", name));
VOID(mi_close(isam_file));
DBUG_RETURN(0);
}
@@ -400,7 +419,7 @@ static MI_INFO *open_isam_file(char *name,int mode)
(share->state.state.records <= 1 ||
share->state.state.data_file_length < 1024))
{
- VOID(fprintf(stderr,"%s is too small to compress\n",name));
+ VOID(fprintf(stderr, "%s is too small to compress\n", name));
VOID(mi_close(isam_file));
DBUG_RETURN(0);
}
@@ -446,8 +465,8 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count)
return 0;
diff_file:
- fprintf(stderr,"%s: Tables '%s' and '%s' are not identical\n",
- my_progname,names[j],names[j+1]);
+ VOID(fprintf(stderr, "%s: Tables '%s' and '%s' are not identical\n",
+ my_progname, names[j], names[j+1]));
error:
while (i--)
mi_close(mrg->file[i]);
@@ -518,16 +537,25 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
mrg->records=0;
for (i=0 ; i < mrg->count ; i++)
mrg->records+=mrg->file[i]->s->state.state.records;
+
+ DBUG_PRINT("info", ("Compressing %s: (%lu records)",
+ result_table ? new_name : org_name,
+ (ulong) mrg->records));
if (write_loop || verbose)
{
- printf("Compressing %s: (%lu records)\n",
- result_table ? new_name : org_name,(ulong) mrg->records);
+ VOID(printf("Compressing %s: (%lu records)\n",
+ result_table ? new_name : org_name, (ulong) mrg->records));
}
trees=fields=share->base.fields;
huff_counts=init_huff_count(isam_file,mrg->records);
QUICK_SAFEMALLOC;
+
+ /*
+ Read the whole data file(s) for statistics.
+ */
+ DBUG_PRINT("info", ("- Calculating statistics"));
if (write_loop || verbose)
- printf("- Calculating statistics\n");
+ VOID(printf("- Calculating statistics\n"));
if (get_statistic(mrg,huff_counts))
goto err;
NORMAL_SAFEMALLOC;
@@ -536,29 +564,74 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
old_length+= (mrg->file[i]->s->state.state.data_file_length -
mrg->file[i]->s->state.state.empty);
+ /*
+ Create a global priority queue in preparation for making
+ temporary Huffman trees.
+ */
if (init_queue(&queue,256,0,0,compare_huff_elements,0))
goto err;
+
+ /*
+ Check each column if we should use pre-space-compress, end-space-
+ compress, empty-field-compress or zero-field-compress.
+ */
check_counts(huff_counts,fields,mrg->records);
+
+ /*
+ Build a Huffman tree for each column.
+ */
huff_trees=make_huff_trees(huff_counts,trees);
+
+ /*
+ If the packed lengths of combined columns is less then the sum of
+ the non-combined columns, then create common Huffman trees for them.
+ We do this only for byte compressed columns, not for distinct values
+ compressed columns.
+ */
if ((int) (used_trees=join_same_trees(huff_counts,trees)) < 0)
goto err;
+
+ /*
+ Assign codes to all byte or column values.
+ */
if (make_huff_decode_table(huff_trees,fields))
goto err;
+ /* Prepare a file buffer. */
init_file_buffer(new_file,0);
+
+ /*
+ Reserve space in the target file for the fixed compressed file header.
+ */
file_buffer.pos_in_file=HEAD_LENGTH;
if (! test_only)
VOID(my_seek(new_file,file_buffer.pos_in_file,MY_SEEK_SET,MYF(0)));
+ /*
+ Write field infos: field type, pack type, length bits, tree number.
+ */
write_field_info(huff_counts,fields,used_trees);
+
+ /*
+ Write decode trees.
+ */
if (!(tot_elements=write_huff_tree(huff_trees,trees)))
goto err;
+
+ /*
+ Calculate the total length of the compression info header.
+ This includes the fixed compressed file header, the column compression
+ type descriptions, and the decode trees.
+ */
header_length=(uint) file_buffer.pos_in_file+
(uint) (file_buffer.pos-file_buffer.buffer);
- /* Compress file */
+ /*
+ Compress the source file into the target file.
+ */
+ DBUG_PRINT("info", ("- Compressing file"));
if (write_loop || verbose)
- printf("- Compressing file\n");
+ VOID(printf("- Compressing file\n"));
error=compress_isam_file(mrg,huff_counts);
new_length=file_buffer.pos_in_file;
if (!error && !test_only)
@@ -568,16 +641,28 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
error=my_write(file_buffer.file,buff,sizeof(buff),
MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
}
+
+ /*
+ Write the fixed compressed file header.
+ */
if (!error)
error=write_header(mrg,header_length,used_trees,tot_elements,
new_length);
+
+ /* Flush the file buffer. */
end_file_buffer();
+ /* Display statistics. */
+ DBUG_PRINT("info", ("Min record length: %6d Max length: %6d "
+ "Mean total length: %6ld\n",
+ mrg->min_pack_length, mrg->max_pack_length,
+ (ulong) (mrg->records ? (new_length/mrg->records) : 0)));
if (verbose && mrg->records)
- printf("Min record length: %6d Max length: %6d Mean total length: %6ld\n",
- mrg->min_pack_length,mrg->max_pack_length,
- (ulong) (new_length/mrg->records));
+ VOID(printf("Min record length: %6d Max length: %6d "
+ "Mean total length: %6ld\n", mrg->min_pack_length,
+ mrg->max_pack_length, (ulong) (new_length/mrg->records)));
+ /* Close source and target file. */
if (!test_only)
{
error|=my_close(new_file,MYF(MY_WME));
@@ -588,6 +673,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
}
}
+ /* Cleanup. */
free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields);
if (! test_only && ! error)
{
@@ -629,15 +715,16 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
error|=my_close(join_isam_file,MYF(MY_WME));
if (error)
{
- VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name));
+ VOID(fprintf(stderr, "Aborting: %s is not compressed\n", org_name));
VOID(my_delete(new_name,MYF(MY_WME)));
DBUG_RETURN(-1);
}
if (write_loop || verbose)
{
if (old_length)
- printf("%.4g%% \n", (((longlong) (old_length -new_length))*100.0/
- (longlong) old_length));
+ VOID(printf("%.4g%% \n",
+ (((longlong) (old_length - new_length)) * 100.0 /
+ (longlong) old_length)));
else
puts("Empty file saved in compressed format");
}
@@ -650,7 +737,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
if (join_isam_file >= 0)
VOID(my_close(join_isam_file,MYF(0)));
mrg_close(mrg);
- VOID(fprintf(stderr,"Aborted: %s is not compressed\n",org_name));
+ VOID(fprintf(stderr, "Aborted: %s is not compressed\n", org_name));
DBUG_RETURN(-1);
}
@@ -677,6 +764,12 @@ static HUFF_COUNTS *init_huff_count(MI_INFO *info,my_off_t records)
(type == FIELD_NORMAL ||
type == FIELD_SKIP_ZERO))
count[i].max_zero_fill= count[i].field_length;
+ /*
+ For every column initialize a tree, which is used to detect distinct
+ column values. 'int_tree' works together with 'tree_buff' and
+ 'tree_pos'. It's keys are implemented by pointers into 'tree_buff'.
+ This is accomplished by '-1' as the element size.
+ */
init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0, NULL,
NULL);
if (records && type != FIELD_BLOB && type != FIELD_VARCHAR)
@@ -762,10 +855,13 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
ulong tot_blob_length=0;
if (! error)
{
+ /* glob_crc is a checksum over all bytes of all records. */
if (static_row_size)
glob_crc+=mi_static_checksum(mrg->file[0],record);
else
glob_crc+=mi_checksum(mrg->file[0],record);
+
+ /* Count the incidence of values separately for every column. */
for (pos=record,count=huff_counts ;
count < end_count ;
count++,
@@ -773,15 +869,48 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
{
next_pos=end_pos=(start_pos=pos)+count->field_length;
- /* Put value in tree if there is room for it */
+ /*
+ Put the whole column value in a tree if there is room for it.
+ 'int_tree' is used to quickly check for duplicate values.
+ 'tree_buff' collects as many distinct column values as
+ possible. If the field length is > 1, it is tree_buff_length,
+ else 2 bytes. Each value is 'field_length' bytes big. If there
+ are more distinct column values than fit into the buffer, we
+ give up with this tree. BLOBs and VARCHARs do not have a
+ tree_buff as it can only be used with fixed length columns.
+ For the special case of field length == 1, we handle only the
+ case that there is only one distinct value in the table(s).
+ Otherwise, we can have a maximum of 256 distinct values. This
+ is then handled by the normal Huffman tree build.
+
+ Another limit for collecting distinct column values is the
+ number of values itself. Since we would need to build a
+ Huffman tree for the values, we are limited by the 'IS_OFFSET'
+ constant. This constant expresses a bit which is used to
+ determine if a tree element holds a final value or an offset
+ to a child element. Hence, all values and offsets need to be
+ smaller than 'IS_OFFSET'. A tree element is implemented with
+ two integer values, one for the left branch and one for the
+ right branch. For the extreme case that the first element
+ points to the last element, the number of integers in the tree
+ must be less or equal to IS_OFFSET. So the number of elements
+ must be less or equal to IS_OFFSET / 2.
+
+ WARNING: At first, we insert a pointer into the record buffer
+ as the key for the tree. If we got a new distinct value, which
+ is really inserted into the tree, instead of being counted
+ only, we will copy the column value from the record buffer to
+ 'tree_buff' and adjust the key pointer of the tree accordingly.
+ */
if (count->tree_buff)
{
global_count=count;
if (!(element=tree_insert(&count->int_tree,pos, 0,
count->int_tree.custom_arg)) ||
(element->count == 1 &&
- count->tree_buff + tree_buff_length <
- count->tree_pos + count->field_length) ||
+ (count->tree_buff + tree_buff_length <
+ count->tree_pos + count->field_length)) ||
+ (count->int_tree.elements_in_tree > IS_OFFSET / 2) ||
(count->field_length == 1 &&
count->int_tree.elements_in_tree > 1))
{
@@ -791,10 +920,17 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
}
else
{
+ /*
+ If tree_insert() succeeds, it either creates a new element
+ or increments the counter of an existing element.
+ */
if (element->count == 1)
- { /* New element */
+ {
+ /* Copy the new column value into 'tree_buff'. */
memcpy(count->tree_pos,pos,(size_t) count->field_length);
+ /* Adjust the key pointer in the tree. */
tree_set_pointer(element,count->tree_pos);
+ /* Point behind the last column value so far. */
count->tree_pos+=count->field_length;
}
}
@@ -804,15 +940,21 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
if (count->field_type == FIELD_NORMAL ||
count->field_type == FIELD_SKIP_ENDSPACE)
{
+ /* Ignore trailing space. */
for ( ; end_pos > pos ; end_pos--)
if (end_pos[-1] != ' ')
break;
+ /* Empty fields are just counted. Go to the next record. */
if (end_pos == pos)
{
count->empty_fields++;
count->max_zero_fill=0;
continue;
}
+ /*
+ Count the total of all trailing spaces and the number of
+ short trailing spaces. Remember the longest trailing space.
+ */
length= (uint) (next_pos-end_pos);
count->tot_end_space+=length;
if (length < 8)
@@ -820,18 +962,25 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
if (count->max_end_space < length)
count->max_end_space = length;
}
+
if (count->field_type == FIELD_NORMAL ||
count->field_type == FIELD_SKIP_PRESPACE)
{
+ /* Ignore leading space. */
for (pos=start_pos; pos < end_pos ; pos++)
if (pos[0] != ' ')
break;
+ /* Empty fields are just counted. Go to the next record. */
if (end_pos == pos)
{
count->empty_fields++;
count->max_zero_fill=0;
continue;
}
+ /*
+ Count the total of all leading spaces and the number of
+ short leading spaces. Remember the longest leading space.
+ */
length= (uint) (pos-start_pos);
count->tot_pre_space+=length;
if (length < 8)
@@ -839,6 +988,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
if (count->max_pre_space < length)
count->max_pre_space = length;
}
+
+ /* Calculate pos, end_pos, and max_length for variable length fields. */
if (count->field_type == FIELD_BLOB)
{
uint field_length=count->field_length -mi_portable_sizeof_char_ptr;
@@ -857,45 +1008,121 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
end_pos= pos+length;
set_if_bigger(count->max_length,length);
}
+
+ /* Evaluate 'max_zero_fill' for short fields. */
if (count->field_length <= 8 &&
(count->field_type == FIELD_NORMAL ||
count->field_type == FIELD_SKIP_ZERO))
{
uint i;
+ /* Zero fields are just counted. Go to the next record. */
if (!memcmp((byte*) start_pos,zero_string,count->field_length))
{
count->zero_fields++;
continue;
}
+ /*
+ max_zero_fill starts with field_length. It is decreased every
+ time a shorter "zero trailer" is found. It is set to zero when
+ an empty field is found (see above). This suggests that the
+ variable should be called 'min_zero_fill'.
+ */
for (i =0 ; i < count->max_zero_fill && ! end_pos[-1 - (int) i] ;
i++) ;
if (i < count->max_zero_fill)
count->max_zero_fill=i;
}
+
+ /* Ignore zero fields and check fields. */
if (count->field_type == FIELD_ZERO ||
count->field_type == FIELD_CHECK)
continue;
+
+ /*
+ Count the incidence of every byte value in the
+ significant field value.
+ */
for ( ; pos < end_pos ; pos++)
count->counts[(uchar) *pos]++;
+
+ /* Step to next field. */
}
+
if (tot_blob_length > max_blob_length)
max_blob_length=tot_blob_length;
record_count++;
if (write_loop && record_count % WRITE_COUNT == 0)
{
- printf("%lu\r",(ulong) record_count); VOID(fflush(stdout));
+ VOID(printf("%lu\r", (ulong) record_count));
+ VOID(fflush(stdout));
}
}
else if (error != HA_ERR_RECORD_DELETED)
{
- fprintf(stderr,"Got error %d while reading rows",error);
+ VOID(fprintf(stderr, "Got error %d while reading rows", error));
break;
}
+
+ /* Step to next record. */
}
if (write_loop)
{
- printf(" \r"); VOID(fflush(stdout));
+ VOID(printf(" \r"));
+ VOID(fflush(stdout));
}
+
+ /*
+ If --debug=d,fakebigcodes is set, fake the counts to get big Huffman
+ codes.
+ */
+ DBUG_EXECUTE_IF("fakebigcodes", fakebigcodes(huff_counts, end_count););
+
+ DBUG_PRINT("info", ("Found the following number of incidents "
+ "of the byte codes:"));
+ if (verbose >= 2)
+ VOID(printf("Found the following number of incidents "
+ "of the byte codes:\n"));
+ for (count= huff_counts ; count < end_count; count++)
+ {
+ uint idx;
+ my_off_t total_count;
+ char llbuf[32];
+
+ DBUG_PRINT("info", ("column: %3u", count - huff_counts + 1));
+ if (verbose >= 2)
+ VOID(printf("column: %3u\n", count - huff_counts + 1));
+ if (count->tree_buff)
+ {
+ DBUG_PRINT("info", ("number of distinct values: %u",
+ (count->tree_pos - count->tree_buff) /
+ count->field_length));
+ if (verbose >= 2)
+ VOID(printf("number of distinct values: %u\n",
+ (count->tree_pos - count->tree_buff) /
+ count->field_length));
+ }
+ total_count= 0;
+ for (idx= 0; idx < 256; idx++)
+ {
+ if (count->counts[idx])
+ {
+ total_count+= count->counts[idx];
+ DBUG_PRINT("info", ("counts[0x%02x]: %12s", idx,
+ llstr((longlong) count->counts[idx], llbuf)));
+ if (verbose >= 2)
+ VOID(printf("counts[0x%02x]: %12s\n", idx,
+ llstr((longlong) count->counts[idx], llbuf)));
+ }
+ }
+ DBUG_PRINT("info", ("total: %12s", llstr((longlong) total_count,
+ llbuf)));
+ if ((verbose >= 2) && total_count)
+ {
+ VOID(printf("total: %12s\n",
+ llstr((longlong) total_count, llbuf)));
+ }
+ }
+
mrg->records=record_count;
mrg->max_blob_length=max_blob_length;
my_afree((gptr) record);
@@ -944,9 +1171,14 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
huff_counts->field_type=FIELD_NORMAL;
huff_counts->pack_type=0;
+ /* Check for zero-filled records (in this column), or zero records. */
if (huff_counts->zero_fields || ! records)
{
my_off_t old_space_count;
+ /*
+ If there are only zero filled records (in this column),
+ or no records at all, we are done.
+ */
if (huff_counts->zero_fields == records)
{
huff_counts->field_type= FIELD_ZERO;
@@ -954,14 +1186,22 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
huff_counts->counts[0]=0;
goto found_pack;
}
+ /* Remeber the number of significant spaces. */
old_space_count=huff_counts->counts[' '];
- huff_counts->counts[' ']+=huff_counts->tot_end_space+
- huff_counts->tot_pre_space +
- huff_counts->empty_fields * huff_counts->field_length;
+ /* Add all leading and trailing spaces. */
+ huff_counts->counts[' ']+= (huff_counts->tot_end_space +
+ huff_counts->tot_pre_space +
+ huff_counts->empty_fields *
+ huff_counts->field_length);
+ /* Check, what the compressed length of this would be. */
old_length=calc_packed_length(huff_counts,0)+records/8;
+ /* Get the number of zero bytes. */
length=huff_counts->zero_fields*huff_counts->field_length;
+ /* Add it to the counts. */
huff_counts->counts[0]+=length;
+ /* Check, what the compressed length of this would be. */
new_length=calc_packed_length(huff_counts,0);
+ /* If the compression without the zeroes would be shorter, we are done. */
if (old_length < new_length && huff_counts->field_length > 1)
{
huff_counts->field_type=FIELD_SKIP_ZERO;
@@ -969,9 +1209,16 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
huff_counts->bytes_packed=old_length- records/8;
goto found_pack;
}
+ /* Remove the insignificant spaces, but keep the zeroes. */
huff_counts->counts[' ']=old_space_count;
}
+ /* Check, what the compressed length of this column would be. */
huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
+
+ /*
+ If there are enough empty records (in this column),
+ treating them specially may pay off.
+ */
if (huff_counts->empty_fields)
{
if (huff_counts->field_length > 2 &&
@@ -1003,6 +1250,11 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
}
}
}
+
+ /*
+ If there are enough trailing spaces (in this column),
+ treating them specially may pay off.
+ */
if (huff_counts->tot_end_space)
{
huff_counts->counts[' ']+=huff_counts->tot_pre_space;
@@ -1012,6 +1264,11 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
goto found_pack;
huff_counts->counts[' ']-=huff_counts->tot_pre_space;
}
+
+ /*
+ If there are enough leading spaces (in this column),
+ treating them specially may pay off.
+ */
if (huff_counts->tot_pre_space)
{
if (test_space_compress(huff_counts,records,huff_counts->max_pre_space,
@@ -1041,6 +1298,8 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
{
HUFF_TREE tree;
+ DBUG_EXECUTE_IF("forceintervall",
+ huff_counts->bytes_packed= ~ (my_off_t) 0;);
tree.element_buffer=0;
if (!make_huff_tree(&tree,huff_counts) &&
tree.bytes_packed+tree.tree_pack_length < huff_counts->bytes_packed)
@@ -1066,14 +1325,27 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
fill_zero_fields++;
field_count[huff_counts->field_type]++;
}
+ DBUG_PRINT("info", ("normal: %3d empty-space: %3d "
+ "empty-zero: %3d empty-fill: %3d",
+ field_count[FIELD_NORMAL],space_fields,
+ field_count[FIELD_SKIP_ZERO],fill_zero_fields));
+ DBUG_PRINT("info", ("pre-space: %3d end-space: %3d "
+ "intervall-fields: %3d zero: %3d",
+ field_count[FIELD_SKIP_PRESPACE],
+ field_count[FIELD_SKIP_ENDSPACE],
+ field_count[FIELD_INTERVALL],
+ field_count[FIELD_ZERO]));
if (verbose)
- printf("\nnormal: %3d empty-space: %3d empty-zero: %3d empty-fill: %3d\npre-space: %3d end-space: %3d intervall-fields: %3d zero: %3d\n",
- field_count[FIELD_NORMAL],space_fields,
- field_count[FIELD_SKIP_ZERO],fill_zero_fields,
- field_count[FIELD_SKIP_PRESPACE],
- field_count[FIELD_SKIP_ENDSPACE],
- field_count[FIELD_INTERVALL],
- field_count[FIELD_ZERO]);
+ VOID(printf("\nnormal: %3d empty-space: %3d "
+ "empty-zero: %3d empty-fill: %3d\n"
+ "pre-space: %3d end-space: %3d "
+ "intervall-fields: %3d zero: %3d\n",
+ field_count[FIELD_NORMAL],space_fields,
+ field_count[FIELD_SKIP_ZERO],fill_zero_fields,
+ field_count[FIELD_SKIP_PRESPACE],
+ field_count[FIELD_SKIP_ENDSPACE],
+ field_count[FIELD_INTERVALL],
+ field_count[FIELD_ZERO]));
DBUG_VOID_RETURN;
}
@@ -1170,8 +1442,24 @@ static HUFF_TREE* make_huff_trees(HUFF_COUNTS *huff_counts, uint trees)
DBUG_RETURN(huff_tree);
}
- /* Update huff_tree according to huff_counts->counts or
- huff_counts->tree_buff */
+/*
+ Build a Huffman tree.
+
+ SYNOPSIS
+ make_huff_tree()
+ huff_tree The Huffman tree.
+ huff_counts The counts.
+
+ DESCRIPTION
+ Build a Huffman tree according to huff_counts->counts or
+ huff_counts->tree_buff. tree_buff, if non-NULL contains up to
+ tree_buff_length of distinct column values. In that case, whole
+ values can be Huffman encoded instead of single bytes.
+
+ RETURN
+ 0 OK
+ != 0 Error
+*/
static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
{
@@ -1182,12 +1470,14 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
first=last=0;
if (huff_counts->tree_buff)
{
+ /* Calculate the number of distinct values in tree_buff. */
found= (uint) (huff_counts->tree_pos - huff_counts->tree_buff) /
huff_counts->field_length;
first=0; last=found-1;
}
else
{
+ /* Count the number of byte codes found in the column. */
for (i=found=0 ; i < 256 ; i++)
{
if (huff_counts->counts[i])
@@ -1201,6 +1491,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
found=2;
}
+ /* When using 'tree_buff' we can have more that 256 values. */
if (queue.max_elements < found)
{
delete_queue(&queue);
@@ -1208,6 +1499,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
return -1;
}
+ /* Allocate or reallocate an element buffer for the Huffman tree. */
if (!huff_tree->element_buffer)
{
if (!(huff_tree->element_buffer=
@@ -1235,15 +1527,25 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
if (huff_counts->tree_buff)
{
huff_tree->elements=0;
- tree_walk(&huff_counts->int_tree,
- (int (*)(void*, element_count,void*)) save_counts_in_queue,
- (gptr) huff_tree, left_root_right);
huff_tree->tree_pack_length=(1+15+16+5+5+
(huff_tree->char_bits+1)*found+
(huff_tree->offset_bits+1)*
(found-2)+7)/8 +
(uint) (huff_tree->counts->tree_pos-
huff_tree->counts->tree_buff);
+ /*
+ Put a HUFF_ELEMENT into the queue for every distinct column value.
+
+ tree_walk() calls save_counts_in_queue() for every element in
+ 'int_tree'. This takes elements from the target trees element
+ buffer and places references to them into the buffer of the
+ priority queue. We insert in column value order, but the order is
+ in fact irrelevant here. We will establish the correct order
+ later.
+ */
+ tree_walk(&huff_counts->int_tree,
+ (int (*)(void*, element_count,void*)) save_counts_in_queue,
+ (gptr) huff_tree, left_root_right);
}
else
{
@@ -1252,7 +1554,15 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
(huff_tree->char_bits+1)*found+
(huff_tree->offset_bits+1)*
(found-2)+7)/8;
+ /*
+ Put a HUFF_ELEMENT into the queue for every byte code found in the column.
+ The elements are taken from the target trees element buffer.
+ Instead of using queue_insert(), we just place references to the
+ elements into the buffer of the priority queue. We insert in byte
+ value order, but the order is in fact irrelevant here. We will
+ establish the correct order later.
+ */
for (i=first, found=0 ; i <= last ; i++)
{
if (huff_counts->counts[i])
@@ -1264,8 +1574,13 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
queue.root[found]=(byte*) new_huff_el;
}
}
+ /*
+ If there is only a single byte value in this field in all records,
+ add a second element with zero incidence. This is required to enter
+ the loop, which builds the Huffman tree.
+ */
while (found < 2)
- { /* Our huff_trees request at least 2 elements */
+ {
new_huff_el=huff_tree->element_buffer+(found++);
new_huff_el->count=0;
new_huff_el->a.leaf.null=0;
@@ -1276,21 +1591,53 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
queue.root[found]=(byte*) new_huff_el;
}
}
+
+ /* Make a queue from the queue buffer. */
queue.elements=found;
+ /*
+ Make a priority queue from the queue. Construct its index so that we
+ have a partially ordered tree.
+ */
for (i=found/2 ; i > 0 ; i--)
_downheap(&queue,i);
+
+ /* The Huffman algorithm. */
bytes_packed=0; bits_packed=0;
for (i=1 ; i < found ; i++)
{
+ /*
+ Pop the top element from the queue (the one with the least incidence).
+ Popping from a priority queue includes a re-ordering of the queue,
+ to get the next least incidence element to the top.
+ */
a=(HUFF_ELEMENT*) queue_remove(&queue,0);
+ /*
+ Copy the next least incidence element. The queue implementation
+ reserves root[0] for temporary purposes. root[1] is the top.
+ */
b=(HUFF_ELEMENT*) queue.root[1];
+ /* Get a new element from the element buffer. */
new_huff_el=huff_tree->element_buffer+found+i;
+ /* The new element gets the sum of the two least incidence elements. */
new_huff_el->count=a->count+b->count;
+ /*
+ The Huffman algorithm assigns another bit to the code for a byte
+ every time that bytes incidence is combined (directly or indirectly)
+ to a new element as one of the two least incidence elements.
+ This means that one more bit per incidence of that byte is required
+ in the resulting file. So we add the new combined incidence as the
+ number of bits by which the result grows.
+ */
bits_packed+=(uint) (new_huff_el->count & 7);
bytes_packed+=new_huff_el->count/8;
- new_huff_el->a.nod.left=a; /* lesser in left */
+ /* The new element points to its children, lesser in left. */
+ new_huff_el->a.nod.left=a;
new_huff_el->a.nod.right=b;
+ /*
+ Replace the copied top element by the new element and re-order the
+ queue.
+ */
queue.root[1]=(byte*) new_huff_el;
queue_replaced(&queue);
}
@@ -1309,7 +1656,26 @@ static int compare_tree(void* cmp_arg __attribute__((unused)),
return 0;
}
- /* Used by make_huff_tree to save intervall-counts in queue */
+/*
+ Organize distinct column values and their incidences into a priority queue.
+
+ SYNOPSIS
+ save_counts_in_queue()
+ key The column value.
+ count The incidence of this value.
+ tree The Huffman tree to be built later.
+
+ DESCRIPTION
+ We use the element buffer of the targeted tree. The distinct column
+ values are organized in a priority queue first. The Huffman
+ algorithm will later organize the elements into a Huffman tree. For
+ the time being, we just place references to the elements into the
+ queue buffer. The buffer will later be organized into a priority
+ queue.
+
+ RETURN
+ 0
+ */
static int save_counts_in_queue(byte *key, element_count count,
HUFF_TREE *tree)
@@ -1326,8 +1692,23 @@ static int save_counts_in_queue(byte *key, element_count count,
}
- /* Calculate length of file if given counts should be used */
- /* Its actually a faster version of make_huff_tree */
+/*
+ Calculate length of file if given counts should be used.
+
+ SYNOPSIS
+ calc_packed_length()
+ huff_counts The counts for a column of the table(s).
+ add_tree_lenght If the decode tree length should be added.
+
+ DESCRIPTION
+ We need to follow the Huffman algorithm until we know, how many bits
+ are required for each byte code. But we do not need the resulting
+ Huffman tree. Hence, we can leave out some steps which are essential
+ in make_huff_tree().
+
+ RETURN
+ Number of bytes required to compress this table column.
+*/
static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
uint add_tree_lenght)
@@ -1337,6 +1718,23 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
HUFF_ELEMENT element_buffer[256];
DBUG_ENTER("calc_packed_length");
+ /*
+ WARNING: We use a small hack for efficiency: Instead of placing
+ references to HUFF_ELEMENTs into the queue, we just insert
+ references to the counts of the byte codes which appeared in this
+ table column. During the Huffman algorithm they are successively
+ replaced by references to HUFF_ELEMENTs. This works, because
+ HUFF_ELEMENTs have the incidence count at their beginning.
+ Regardless, wether the queue array contains references to counts of
+ type my_off_t or references to HUFF_ELEMENTs which have the count of
+ type my_off_t at their beginning, it always points to a count of the
+ same type.
+
+ Instead of using queue_insert(), we just copy the references into
+ the buffer of the priority queue. We insert in byte value order, but
+ the order is in fact irrelevant here. We will establish the correct
+ order later.
+ */
first=last=0;
for (i=found=0 ; i < 256 ; i++)
{
@@ -1345,31 +1743,73 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
if (! found++)
first=i;
last=i;
+ /* We start with root[1], which is the queues top element. */
queue.root[found]=(byte*) &huff_counts->counts[i];
}
}
if (!found)
DBUG_RETURN(0); /* Empty tree */
+ /*
+ If there is only a single byte value in this field in all records,
+ add a second element with zero incidence. This is required to enter
+ the loop, which follows the Huffman algorithm.
+ */
if (found < 2)
queue.root[++found]=(byte*) &huff_counts->counts[last ? 0 : 1];
+ /* Make a queue from the queue buffer. */
queue.elements=found;
bytes_packed=0; bits_packed=0;
+ /* Add the length of the coding table, which would become part of the file. */
if (add_tree_lenght)
bytes_packed=(8+9+5+5+(max_bit(last-first)+1)*found+
(max_bit(found-1)+1+1)*(found-2) +7)/8;
+
+ /*
+ Make a priority queue from the queue. Construct its index so that we
+ have a partially ordered tree.
+ */
for (i=(found+1)/2 ; i > 0 ; i--)
_downheap(&queue,i);
+
+ /* The Huffman algorithm. */
for (i=0 ; i < found-1 ; i++)
{
- HUFF_ELEMENT *a,*b,*new_huff_el;
- a=(HUFF_ELEMENT*) queue_remove(&queue,0);
- b=(HUFF_ELEMENT*) queue.root[1];
- new_huff_el=element_buffer+i;
- new_huff_el->count=a->count+b->count;
+ my_off_t *a;
+ my_off_t *b;
+ HUFF_ELEMENT *new_huff_el;
+
+ /*
+ Pop the top element from the queue (the one with the least
+ incidence). Popping from a priority queue includes a re-ordering
+ of the queue, to get the next least incidence element to the top.
+ */
+ a= (my_off_t*) queue_remove(&queue, 0);
+ /*
+ Copy the next least incidence element. The queue implementation
+ reserves root[0] for temporary purposes. root[1] is the top.
+ */
+ b= (my_off_t*) queue.root[1];
+ /* Create a new element in a local (automatic) buffer. */
+ new_huff_el= element_buffer + i;
+ /* The new element gets the sum of the two least incidence elements. */
+ new_huff_el->count= *a + *b;
+ /*
+ The Huffman algorithm assigns another bit to the code for a byte
+ every time that bytes incidence is combined (directly or indirectly)
+ to a new element as one of the two least incidence elements.
+ This means that one more bit per incidence of that byte is required
+ in the resulting file. So we add the new combined incidence as the
+ number of bits by which the result grows.
+ */
bits_packed+=(uint) (new_huff_el->count & 7);
bytes_packed+=new_huff_el->count/8;
+ /*
+ Replace the copied top element by the new element and re-order the
+ queue. This successively replaces the references to counts by
+ references to HUFF_ELEMENTs.
+ */
queue.root[1]=(byte*) new_huff_el;
queue_replaced(&queue);
}
@@ -1417,13 +1857,26 @@ static uint join_same_trees(HUFF_COUNTS *huff_counts, uint trees)
}
}
}
+ DBUG_PRINT("info", ("Original trees: %d After join: %d",
+ trees, tree_number));
if (verbose)
- printf("Original trees: %d After join: %d\n",trees,tree_number);
+ VOID(printf("Original trees: %d After join: %d\n", trees, tree_number));
return tree_number; /* Return trees left */
}
- /* Fill in huff_tree decode tables */
+/*
+ Fill in huff_tree encode tables.
+
+ SYNOPSIS
+ make_huff_decode_table()
+ huff_tree An array of HUFF_TREE which are to be encoded.
+ trees The number of HUFF_TREE in the array.
+
+ RETURN
+ 0 success
+ != 0 error
+*/
static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees)
{
@@ -1434,12 +1887,13 @@ static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees)
{
elements=huff_tree->counts->tree_buff ? huff_tree->elements : 256;
if (!(huff_tree->code =
- (ulong*) my_malloc(elements*
- (sizeof(ulong)+sizeof(uchar)),
- MYF(MY_WME | MY_ZEROFILL))))
+ (ulonglong*) my_malloc(elements*
+ (sizeof(ulonglong) + sizeof(uchar)),
+ MYF(MY_WME | MY_ZEROFILL))))
return 1;
huff_tree->code_len=(uchar*) (huff_tree->code+elements);
- make_traverse_code_tree(huff_tree,huff_tree->root,32,0);
+ make_traverse_code_tree(huff_tree, huff_tree->root,
+ 8 * sizeof(ulonglong), LL(0));
}
}
return 0;
@@ -1448,28 +1902,90 @@ static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees)
static void make_traverse_code_tree(HUFF_TREE *huff_tree,
HUFF_ELEMENT *element,
- uint size, ulong code)
+ uint size, ulonglong code)
{
uint chr;
if (!element->a.leaf.null)
{
chr=element->a.leaf.element_nr;
- huff_tree->code_len[chr]=(uchar) (32-size);
- huff_tree->code[chr]= (code >> size);
- if (huff_tree->height < 32-size)
- huff_tree->height= 32-size;
+ huff_tree->code_len[chr]= (uchar) (8 * sizeof(ulonglong) - size);
+ huff_tree->code[chr]= (code >> size);
+ if (huff_tree->height < 8 * sizeof(ulonglong) - size)
+ huff_tree->height= 8 * sizeof(ulonglong) - size;
}
else
{
size--;
make_traverse_code_tree(huff_tree,element->a.nod.left,size,code);
- make_traverse_code_tree(huff_tree,element->a.nod.right,size,
- code+((ulong) 1L << size));
+ make_traverse_code_tree(huff_tree, element->a.nod.right, size,
+ code + (((ulonglong) 1) << size));
}
return;
}
+/*
+ Convert a value into binary digits.
+
+ SYNOPSIS
+ bindigits()
+ value The value.
+ length The number of low order bits to convert.
+
+ NOTE
+ The result string is in static storage. It is reused on every call.
+ So you cannot use it twice in one expression.
+
+ RETURN
+ A pointer to a static NUL-terminated string.
+ */
+
+static char *bindigits(ulonglong value, uint bits)
+{
+ static char digits[72];
+ char *ptr= digits;
+ uint idx= bits;
+
+ DBUG_ASSERT(idx < sizeof(digits));
+ while (idx)
+ *(ptr++)= '0' + ((value >> (--idx)) & 1);
+ *ptr= '\0';
+ return digits;
+}
+
+
+/*
+ Convert a value into hexadecimal digits.
+
+ SYNOPSIS
+ hexdigits()
+ value The value.
+
+ NOTE
+ The result string is in static storage. It is reused on every call.
+ So you cannot use it twice in one expression.
+
+ RETURN
+ A pointer to a static NUL-terminated string.
+ */
+
+static char *hexdigits(ulonglong value)
+{
+ static char digits[20];
+ char *ptr= digits;
+ uint idx= 2 * sizeof(value); /* Two hex digits per byte. */
+
+ DBUG_ASSERT(idx < sizeof(digits));
+ while (idx)
+ {
+ if ((*(ptr++)= '0' + ((value >> (4 * (--idx))) & 0xf)) > '9')
+ *(ptr - 1)+= 'a' - '9' - 1;
+ }
+ *ptr= '\0';
+ return digits;
+}
+
+
/* Write header to new packed data file */
static int write_header(PACK_MRG_INFO *mrg,uint head_length,uint trees,
@@ -1503,15 +2019,64 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees)
uint huff_tree_bits;
huff_tree_bits=max_bit(trees ? trees-1 : 0);
+ DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", ("column types:"));
+ DBUG_PRINT("info", ("FIELD_NORMAL 0"));
+ DBUG_PRINT("info", ("FIELD_SKIP_ENDSPACE 1"));
+ DBUG_PRINT("info", ("FIELD_SKIP_PRESPACE 2"));
+ DBUG_PRINT("info", ("FIELD_SKIP_ZERO 3"));
+ DBUG_PRINT("info", ("FIELD_BLOB 4"));
+ DBUG_PRINT("info", ("FIELD_CONSTANT 5"));
+ DBUG_PRINT("info", ("FIELD_INTERVALL 6"));
+ DBUG_PRINT("info", ("FIELD_ZERO 7"));
+ DBUG_PRINT("info", ("FIELD_VARCHAR 8"));
+ DBUG_PRINT("info", ("FIELD_CHECK 9"));
+ DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", ("pack type as a set of flags:"));
+ DBUG_PRINT("info", ("PACK_TYPE_SELECTED 1"));
+ DBUG_PRINT("info", ("PACK_TYPE_SPACE_FIELDS 2"));
+ DBUG_PRINT("info", ("PACK_TYPE_ZERO_FILL 4"));
+ DBUG_PRINT("info", (""));
+ if (verbose >= 2)
+ {
+ VOID(printf("\n"));
+ VOID(printf("column types:\n"));
+ VOID(printf("FIELD_NORMAL 0\n"));
+ VOID(printf("FIELD_SKIP_ENDSPACE 1\n"));
+ VOID(printf("FIELD_SKIP_PRESPACE 2\n"));
+ VOID(printf("FIELD_SKIP_ZERO 3\n"));
+ VOID(printf("FIELD_BLOB 4\n"));
+ VOID(printf("FIELD_CONSTANT 5\n"));
+ VOID(printf("FIELD_INTERVALL 6\n"));
+ VOID(printf("FIELD_ZERO 7\n"));
+ VOID(printf("FIELD_VARCHAR 8\n"));
+ VOID(printf("FIELD_CHECK 9\n"));
+ VOID(printf("\n"));
+ VOID(printf("pack type as a set of flags:\n"));
+ VOID(printf("PACK_TYPE_SELECTED 1\n"));
+ VOID(printf("PACK_TYPE_SPACE_FIELDS 2\n"));
+ VOID(printf("PACK_TYPE_ZERO_FILL 4\n"));
+ VOID(printf("\n"));
+ }
for (i=0 ; i++ < fields ; counts++)
{
- write_bits((ulong) (int) counts->field_type,5);
+ write_bits((ulonglong) (int) counts->field_type, 5);
write_bits(counts->pack_type,6);
if (counts->pack_type & PACK_TYPE_ZERO_FILL)
write_bits(counts->max_zero_fill,5);
else
write_bits(counts->length_bits,5);
- write_bits((ulong) counts->tree->tree_number-1,huff_tree_bits);
+ write_bits((ulonglong) counts->tree->tree_number - 1, huff_tree_bits);
+ DBUG_PRINT("info", ("column: %3u type: %2u pack: %2u zero: %4u "
+ "lbits: %2u tree: %2u length: %4u",
+ i , counts->field_type, counts->pack_type,
+ counts->max_zero_fill, counts->length_bits,
+ counts->tree->tree_number, counts->field_length));
+ if (verbose >= 2)
+ VOID(printf("column: %3u type: %2u pack: %2u zero: %4u lbits: %2u "
+ "tree: %2u length: %4u\n", i , counts->field_type,
+ counts->pack_type, counts->max_zero_fill, counts->length_bits,
+ counts->tree->tree_number, counts->field_length));
}
flush_bits();
return;
@@ -1524,45 +2089,72 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees)
static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
{
uint i,int_length;
+ uint tree_no;
+ uint codes;
+ uint errors= 0;
uint *packed_tree,*offset,length;
my_off_t elements;
+ /* Find the highest number of elements in the trees. */
for (i=length=0 ; i < trees ; i++)
if (huff_tree[i].tree_number > 0 && huff_tree[i].elements > length)
length=huff_tree[i].elements;
+ /*
+ Allocate a buffer for packing a decode tree. Two numbers per element
+ (left child and right child).
+ */
if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2)))
{
my_error(EE_OUTOFMEMORY,MYF(ME_BELL),sizeof(uint)*length*2);
return 0;
}
+ DBUG_PRINT("info", (""));
+ if (verbose >= 2)
+ VOID(printf("\n"));
+ tree_no= 0;
intervall_length=0;
for (elements=0; trees-- ; huff_tree++)
{
+ /* Skip columns that have been joined with other columns. */
if (huff_tree->tree_number == 0)
continue; /* Deleted tree */
+ tree_no++;
+ DBUG_PRINT("info", (""));
+ if (verbose >= 3)
+ VOID(printf("\n"));
+ /* Count the total number of elements (byte codes or column values). */
elements+=huff_tree->elements;
huff_tree->max_offset=2;
+ /* Build a tree of offsets and codes for decoding in 'packed_tree'. */
if (huff_tree->elements <= 1)
offset=packed_tree;
else
offset=make_offset_code_tree(huff_tree,huff_tree->root,packed_tree);
+
+ /* This should be the same as 'length' above. */
huff_tree->offset_bits=max_bit(huff_tree->max_offset);
+
+ /*
+ Since we check this during collecting the distinct column values,
+ this should never happen.
+ */
if (huff_tree->max_offset >= IS_OFFSET)
{ /* This should be impossible */
- VOID(fprintf(stderr,"Tree offset got too big: %d, aborted\n",
- huff_tree->max_offset));
+ VOID(fprintf(stderr, "Tree offset got too big: %d, aborted\n",
+ huff_tree->max_offset));
my_afree((gptr) packed_tree);
return 0;
}
-#ifdef EXTRA_DBUG
- printf("pos: %d elements: %d tree-elements: %d char_bits: %d\n",
- (uint) (file_buffer.pos-file_buffer.buffer),
- huff_tree->elements, (offset-packed_tree),huff_tree->char_bits);
-#endif
+ DBUG_PRINT("info", ("pos: %lu elements: %u tree-elements: %lu "
+ "char_bits: %u\n",
+ (ulong) (file_buffer.pos - file_buffer.buffer),
+ huff_tree->elements, (ulong) (offset - packed_tree),
+ huff_tree->char_bits));
if (!huff_tree->counts->tree_buff)
{
+ /* We do a byte compression on this column. Mark with bit 0. */
write_bits(0,1);
write_bits(huff_tree->min_chr,8);
write_bits(huff_tree->elements,9);
@@ -1574,6 +2166,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
{
int_length=(uint) (huff_tree->counts->tree_pos -
huff_tree->counts->tree_buff);
+ /* We have distinct column values for this column. Mark with bit 1. */
write_bits(1,1);
write_bits(huff_tree->elements,15);
write_bits(int_length,16);
@@ -1581,10 +2174,29 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
write_bits(huff_tree->offset_bits,5);
intervall_length+=int_length;
}
+ DBUG_PRINT("info", ("tree: %2u elements: %4u char_bits: %2u "
+ "offset_bits: %2u %s: %5u codelen: %2u",
+ tree_no, huff_tree->elements, huff_tree->char_bits,
+ huff_tree->offset_bits, huff_tree->counts->tree_buff ?
+ "bufflen" : "min_chr", huff_tree->counts->tree_buff ?
+ int_length : huff_tree->min_chr, huff_tree->height));
+ if (verbose >= 2)
+ VOID(printf("tree: %2u elements: %4u char_bits: %2u offset_bits: %2u "
+ "%s: %5u codelen: %2u\n", tree_no, huff_tree->elements,
+ huff_tree->char_bits, huff_tree->offset_bits,
+ huff_tree->counts->tree_buff ? "bufflen" : "min_chr",
+ huff_tree->counts->tree_buff ? int_length :
+ huff_tree->min_chr, huff_tree->height));
+
+ /* Check that the code tree length matches the element count. */
length=(uint) (offset-packed_tree);
if (length != huff_tree->elements*2-2)
- printf("error: Huff-tree-length: %d != calc_length: %d\n",
- length,huff_tree->elements*2-2);
+ {
+ VOID(fprintf(stderr, "error: Huff-tree-length: %d != calc_length: %d\n",
+ length, huff_tree->elements * 2 - 2));
+ errors++;
+ break;
+ }
for (i=0 ; i < length ; i++)
{
@@ -1593,16 +2205,122 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
huff_tree->offset_bits+1);
else
write_bits(packed_tree[i]-huff_tree->min_chr,huff_tree->char_bits+1);
+ DBUG_PRINT("info", ("tree[0x%04x]: %s0x%04x",
+ i, (packed_tree[i] & IS_OFFSET) ?
+ " -> " : "", (packed_tree[i] & IS_OFFSET) ?
+ packed_tree[i] - IS_OFFSET + i : packed_tree[i]));
+ if (verbose >= 3)
+ VOID(printf("tree[0x%04x]: %s0x%04x\n",
+ i, (packed_tree[i] & IS_OFFSET) ? " -> " : "",
+ (packed_tree[i] & IS_OFFSET) ?
+ packed_tree[i] - IS_OFFSET + i : packed_tree[i]));
}
flush_bits();
+
+ /*
+ Display coding tables and check their correctness.
+ */
+ codes= huff_tree->counts->tree_buff ? huff_tree->elements : 256;
+ for (i= 0; i < codes; i++)
+ {
+ ulonglong code;
+ uint bits;
+ uint len;
+ uint idx;
+
+ if (! (len= huff_tree->code_len[i]))
+ continue;
+ DBUG_PRINT("info", ("code[0x%04x]: 0x%s bits: %2u bin: %s", i,
+ hexdigits(huff_tree->code[i]), huff_tree->code_len[i],
+ bindigits(huff_tree->code[i],
+ huff_tree->code_len[i])));
+ if (verbose >= 3)
+ VOID(printf("code[0x%04x]: 0x%s bits: %2u bin: %s\n", i,
+ hexdigits(huff_tree->code[i]), huff_tree->code_len[i],
+ bindigits(huff_tree->code[i], huff_tree->code_len[i])));
+
+ /* Check that the encode table decodes correctly. */
+ code= 0;
+ bits= 0;
+ idx= 0;
+ DBUG_EXECUTE_IF("forcechkerr1", len--;);
+ DBUG_EXECUTE_IF("forcechkerr2", bits= 8 * sizeof(code););
+ DBUG_EXECUTE_IF("forcechkerr3", idx= length;);
+ for (;;)
+ {
+ if (! len)
+ {
+ VOID(fflush(stdout));
+ VOID(fprintf(stderr, "error: code 0x%s with %u bits not found\n",
+ hexdigits(huff_tree->code[i]), huff_tree->code_len[i]));
+ errors++;
+ break;
+ }
+ code<<= 1;
+ code|= (huff_tree->code[i] >> (--len)) & 1;
+ bits++;
+ if (bits > 8 * sizeof(code))
+ {
+ VOID(fflush(stdout));
+ VOID(fprintf(stderr, "error: Huffman code too long: %u/%u\n",
+ bits, 8 * sizeof(code)));
+ errors++;
+ break;
+ }
+ idx+= code & 1;
+ if (idx >= length)
+ {
+ VOID(fflush(stdout));
+ VOID(fprintf(stderr, "error: illegal tree offset: %u/%u\n",
+ idx, length));
+ errors++;
+ break;
+ }
+ if (packed_tree[idx] & IS_OFFSET)
+ idx+= packed_tree[idx] & ~IS_OFFSET;
+ else
+ break; /* Hit a leaf. This contains the result value. */
+ }
+ if (errors)
+ break;
+
+ DBUG_EXECUTE_IF("forcechkerr4", packed_tree[idx]++;);
+ if (packed_tree[idx] != i)
+ {
+ VOID(fflush(stdout));
+ VOID(fprintf(stderr, "error: decoded value 0x%04x should be: 0x%04x\n",
+ packed_tree[idx], i));
+ errors++;
+ break;
+ }
+ } /*end for (codes)*/
+ if (errors)
+ break;
+
+ /* Write column values in case of distinct column value compression. */
if (huff_tree->counts->tree_buff)
{
for (i=0 ; i < int_length ; i++)
- write_bits((uint) (uchar) huff_tree->counts->tree_buff[i],8);
+ {
+ write_bits((ulonglong) (uchar) huff_tree->counts->tree_buff[i], 8);
+ DBUG_PRINT("info", ("column_values[0x%04x]: 0x%02x",
+ i, (uchar) huff_tree->counts->tree_buff[i]));
+ if (verbose >= 3)
+ VOID(printf("column_values[0x%04x]: 0x%02x\n",
+ i, (uchar) huff_tree->counts->tree_buff[i]));
+ }
}
flush_bits();
}
+ DBUG_PRINT("info", (""));
+ if (verbose >= 2)
+ VOID(printf("\n"));
my_afree((gptr) packed_tree);
+ if (errors)
+ {
+ VOID(fprintf(stderr, "Error: Generated decode trees are corrupt. Stop.\n"));
+ return 0;
+ }
return elements;
}
@@ -1613,23 +2331,43 @@ static uint *make_offset_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element,
uint *prev_offset;
prev_offset= offset;
+ /*
+ 'a.leaf.null' takes the same place as 'a.nod.left'. If this is null,
+ then there is no left child and, hence no right child either. This
+ is a property of a binary tree. An element is either a node with two
+ childs, or a leaf without childs.
+
+ The current element is always a node with two childs. Go left first.
+ */
if (!element->a.nod.left->a.leaf.null)
{
- offset[0] =(uint) element->a.nod.left->a.leaf.element_nr;
+ /* Store the byte code or the index of the column value. */
+ prev_offset[0] =(uint) element->a.nod.left->a.leaf.element_nr;
offset+=2;
}
else
{
+ /*
+ Recursively traverse the tree to the left. Mark it as an offset to
+ another tree node (in contrast to a byte code or column value index).
+ */
prev_offset[0]= IS_OFFSET+2;
offset=make_offset_code_tree(huff_tree,element->a.nod.left,offset+2);
}
+
+ /* Now, check the right child. */
if (!element->a.nod.right->a.leaf.null)
{
+ /* Store the byte code or the index of the column value. */
prev_offset[1]=element->a.nod.right->a.leaf.element_nr;
return offset;
}
else
{
+ /*
+ Recursively traverse the tree to the right. Mark it as an offset to
+ another tree node (in contrast to a byte code or column value index).
+ */
uint temp=(uint) (offset-prev_offset-1);
prev_offset[1]= IS_OFFSET+ temp;
if (huff_tree->max_offset < temp)
@@ -1656,6 +2394,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
uint i,max_calc_length,pack_ref_length,min_record_length,max_record_length,
intervall,field_length,max_pack_length,pack_blob_length;
my_off_t record_count;
+ char llbuf[32];
ulong length,pack_length;
byte *record,*pos,*end_pos,*record_pos,*start_pos;
HUFF_COUNTS *count,*end_count;
@@ -1663,12 +2402,23 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
MI_INFO *isam_file=mrg->file[0];
DBUG_ENTER("compress_isam_file");
+ /* Allocate a buffer for the records (excluding blobs). */
if (!(record=(byte*) my_alloca(isam_file->s->base.reclength)))
return -1;
+
end_count=huff_counts+isam_file->s->base.fields;
min_record_length= (uint) ~0;
max_record_length=0;
+ /*
+ Calculate the maximum number of bits required to pack the records.
+ Remember to understand 'max_zero_fill' as 'min_zero_fill'.
+ The tree height determines the maximum number of bits per value.
+ Some fields skip leading or trailing spaces or zeroes. The skipped
+ number of bytes is encoded by 'length_bits' bits.
+ Empty blobs and varchar are encoded with a single 1 bit. Other blobs
+ and varchar get a leading 0 bit.
+ */
for (i=max_calc_length=0 ; i < isam_file->s->base.fields ; i++)
{
if (!(huff_counts[i].pack_type & PACK_TYPE_ZERO_FILL))
@@ -1687,14 +2437,16 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
(huff_counts[i].field_length - huff_counts[i].max_zero_fill)*
huff_counts[i].tree->height+huff_counts[i].length_bits;
}
- max_calc_length/=8;
+ max_calc_length= (max_calc_length + 7) / 8;
if (max_calc_length < 254)
pack_ref_length=1;
else if (max_calc_length <= 65535)
pack_ref_length=3;
else
pack_ref_length=4;
+
record_count=0;
+ /* 'max_blob_length' is the max length of all blobs of a record. */
pack_blob_length=0;
if (isam_file->s->base.blobs)
{
@@ -1707,6 +2459,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
}
max_pack_length=pack_ref_length+pack_blob_length;
+ DBUG_PRINT("fields", ("==="));
mrg_reset(mrg);
while ((error=mrg_rrnd(mrg,record)) != HA_ERR_END_OF_FILE)
{
@@ -1722,15 +2475,29 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
end_pos=start_pos+(field_length=count->field_length);
tree=count->tree;
+ DBUG_PRINT("fields", ("column: %3lu type: %2u pack: %2u zero: %4u "
+ "lbits: %2u tree: %2u length: %4u",
+ (ulong) (count - huff_counts + 1),
+ count->field_type,
+ count->pack_type, count->max_zero_fill,
+ count->length_bits, count->tree->tree_number,
+ count->field_length));
+
+ /* Check if the column contains spaces only. */
if (count->pack_type & PACK_TYPE_SPACE_FIELDS)
{
for (pos=start_pos ; *pos == ' ' && pos < end_pos; pos++) ;
if (pos == end_pos)
{
+ DBUG_PRINT("fields",
+ ("PACK_TYPE_SPACE_FIELDS spaces only, bits: 1"));
+ DBUG_PRINT("fields", ("---"));
write_bits(1,1);
start_pos=end_pos;
continue;
}
+ DBUG_PRINT("fields",
+ ("PACK_TYPE_SPACE_FIELDS not only spaces, bits: 1"));
write_bits(0,1);
}
end_pos-=count->max_zero_fill;
@@ -1740,65 +2507,129 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
case FIELD_SKIP_ZERO:
if (!memcmp((byte*) start_pos,zero_string,field_length))
{
+ DBUG_PRINT("fields", ("FIELD_SKIP_ZERO zeroes only, bits: 1"));
write_bits(1,1);
start_pos=end_pos;
break;
}
+ DBUG_PRINT("fields", ("FIELD_SKIP_ZERO not only zeroes, bits: 1"));
write_bits(0,1);
/* Fall through */
case FIELD_NORMAL:
+ DBUG_PRINT("fields", ("FIELD_NORMAL %lu bytes",
+ (ulong) (end_pos - start_pos)));
for ( ; start_pos < end_pos ; start_pos++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *start_pos,
+ hexdigits(tree->code[(uchar) *start_pos]),
+ (uint) tree->code_len[(uchar) *start_pos],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint) tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
+ }
break;
case FIELD_SKIP_ENDSPACE:
for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ;
- length=(uint) (end_pos-pos);
+ length= (ulong) (end_pos - pos);
if (count->pack_type & PACK_TYPE_SELECTED)
{
if (length > count->min_space)
{
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_ENDSPACE more than min_space, bits: 1"));
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u",
+ length, field_length, count->length_bits));
write_bits(1,1);
write_bits(length,count->length_bits);
}
else
{
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_ENDSPACE not more than min_space, "
+ "bits: 1"));
write_bits(0,1);
pos=end_pos;
}
}
else
+ {
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u",
+ length, field_length, count->length_bits));
write_bits(length,count->length_bits);
+ }
+ /* Encode all significant bytes. */
+ DBUG_PRINT("fields", ("FIELD_SKIP_ENDSPACE %lu bytes",
+ (ulong) (pos - start_pos)));
for ( ; start_pos < pos ; start_pos++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *start_pos,
+ hexdigits(tree->code[(uchar) *start_pos]),
+ (uint) tree->code_len[(uchar) *start_pos],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint) tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
+ }
start_pos=end_pos;
break;
case FIELD_SKIP_PRESPACE:
for (pos=start_pos ; pos < end_pos && pos[0] == ' ' ; pos++) ;
- length=(uint) (pos-start_pos);
+ length= (ulong) (pos - start_pos);
if (count->pack_type & PACK_TYPE_SELECTED)
{
if (length > count->min_space)
{
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_PRESPACE more than min_space, bits: 1"));
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u",
+ length, field_length, count->length_bits));
write_bits(1,1);
write_bits(length,count->length_bits);
}
else
{
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_PRESPACE not more than min_space, "
+ "bits: 1"));
pos=start_pos;
write_bits(0,1);
}
}
else
+ {
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u",
+ length, field_length, count->length_bits));
write_bits(length,count->length_bits);
+ }
+ /* Encode all significant bytes. */
+ DBUG_PRINT("fields", ("FIELD_SKIP_PRESPACE %lu bytes",
+ (ulong) (end_pos - start_pos)));
for (start_pos=pos ; start_pos < end_pos ; start_pos++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *start_pos,
+ hexdigits(tree->code[(uchar) *start_pos]),
+ (uint) tree->code_len[(uchar) *start_pos],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint) tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
+ }
break;
case FIELD_CONSTANT:
case FIELD_ZERO:
case FIELD_CHECK:
+ DBUG_PRINT("fields", ("FIELD_CONSTANT/ZERO/CHECK"));
start_pos=end_pos;
break;
case FIELD_INTERVALL:
@@ -1806,6 +2637,10 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
pos=(byte*) tree_search(&count->int_tree, start_pos,
count->int_tree.custom_arg);
intervall=(uint) (pos - count->tree_buff)/field_length;
+ DBUG_PRINT("fields", ("FIELD_INTERVALL"));
+ DBUG_PRINT("fields", ("index: %4u code: 0x%s bits: %2u",
+ intervall, hexdigits(tree->code[intervall]),
+ (uint) tree->code_len[intervall]));
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
start_pos=end_pos;
break;
@@ -1814,21 +2649,36 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
ulong blob_length=_mi_calc_blob_length(field_length-
mi_portable_sizeof_char_ptr,
start_pos);
+ /* Empty blobs are encoded with a single 1 bit. */
if (!blob_length)
{
- write_bits(1,1); /* Empty blob */
+ DBUG_PRINT("fields", ("FIELD_BLOB empty, bits: 1"));
+ write_bits(1,1);
}
else
{
byte *blob,*blob_end;
+ DBUG_PRINT("fields", ("FIELD_BLOB not empty, bits: 1"));
write_bits(0,1);
+ /* Write the blob length. */
+ DBUG_PRINT("fields", ("FIELD_BLOB %lu bytes, bits: %2u",
+ blob_length, count->length_bits));
write_bits(blob_length,count->length_bits);
memcpy_fixed(&blob,end_pos-mi_portable_sizeof_char_ptr,
sizeof(char*));
blob_end=blob+blob_length;
+ /* Encode the blob bytes. */
for ( ; blob < blob_end ; blob++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *blob, hexdigits(tree->code[(uchar) *blob]),
+ (uint) tree->code_len[(uchar) *blob],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint)tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *blob],
(uint) tree->code_len[(uchar) *blob]);
+ }
tot_blob_length+=blob_length;
}
start_pos= end_pos;
@@ -1839,18 +2689,34 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
ulong col_length= (pack_length == 1 ? (uint) *(uchar*) start_pos :
uint2korr(start_pos));
+ /* Empty varchar are encoded with a single 1 bit. */
if (!col_length)
{
+ DBUG_PRINT("fields", ("FIELD_VARCHAR empty, bits: 1"));
write_bits(1,1); /* Empty varchar */
}
else
{
byte *end=start_pos+pack_length+col_length;
+ DBUG_PRINT("fields", ("FIELD_VARCHAR not empty, bits: 1"));
write_bits(0,1);
+ /* Write the varchar length. */
+ DBUG_PRINT("fields", ("FIELD_VARCHAR %lu bytes, bits: %2u",
+ col_length, count->length_bits));
write_bits(col_length,count->length_bits);
+ /* Encode the varchar bytes. */
for (start_pos+=pack_length ; start_pos < end ; start_pos++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *start_pos,
+ hexdigits(tree->code[(uchar) *start_pos]),
+ (uint) tree->code_len[(uchar) *start_pos],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint)tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
+ }
}
start_pos= end_pos;
break;
@@ -1859,12 +2725,17 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
abort(); /* Impossible */
}
start_pos+=count->max_zero_fill;
+ DBUG_PRINT("fields", ("---"));
}
flush_bits();
- length=(ulong) (file_buffer.pos-record_pos)-max_pack_length;
+ length=(ulong) ((byte*) file_buffer.pos - record_pos) - max_pack_length;
pack_length=save_pack_length(record_pos,length);
if (pack_blob_length)
pack_length+=save_pack_length(record_pos+pack_length,tot_blob_length);
+ DBUG_PRINT("fields", ("record: %lu length: %lu blob-length: %lu "
+ "length-bytes: %lu", (ulong) record_count, length,
+ tot_blob_length, pack_length));
+ DBUG_PRINT("fields", ("==="));
/* Correct file buffer if the header was smaller */
if (pack_length != max_pack_length)
@@ -1876,9 +2747,11 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
min_record_length=(uint) length;
if (length > (ulong) max_record_length)
max_record_length=(uint) length;
- if (write_loop && ++record_count % WRITE_COUNT == 0)
+ record_count++;
+ if (write_loop && record_count % WRITE_COUNT == 0)
{
- printf("%lu\r",(ulong) record_count); VOID(fflush(stdout));
+ VOID(printf("%lu\r", (ulong) record_count));
+ VOID(fflush(stdout));
}
}
else if (error != HA_ERR_RECORD_DELETED)
@@ -1888,8 +2761,11 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
error=0;
else
{
- fprintf(stderr,"%s: Got error %d reading records\n",my_progname,error);
+ VOID(fprintf(stderr, "%s: Got error %d reading records\n",
+ my_progname, error));
}
+ if (verbose >= 2)
+ VOID(printf("wrote %s records.\n", llstr((longlong) record_count, llbuf)));
my_afree((gptr) record);
mrg->ref_length=max_pack_length;
@@ -1929,7 +2805,7 @@ static void init_file_buffer(File file, pbool read_buffer)
file_buffer.pos=file_buffer.buffer;
file_buffer.bits=BITS_SAVED;
}
- file_buffer.current_byte=0;
+ file_buffer.bitbucket= 0;
}
@@ -1972,7 +2848,8 @@ static int flush_buffer(ulong neaded_length)
tmp=my_realloc(file_buffer.buffer, neaded_length,MYF(MY_WME));
if (!tmp)
return 1;
- file_buffer.pos= tmp + (ulong) (file_buffer.pos - file_buffer.buffer);
+ file_buffer.pos= ((uchar*) tmp +
+ (ulong) (file_buffer.pos - file_buffer.buffer));
file_buffer.buffer=tmp;
file_buffer.end=tmp+neaded_length-8;
}
@@ -1987,68 +2864,59 @@ static void end_file_buffer(void)
/* output `bits` low bits of `value' */
-static void write_bits (register ulong value, register uint bits)
+static void write_bits(register ulonglong value, register uint bits)
{
- if ((file_buffer.bits-=(int) bits) >= 0)
+ DBUG_ASSERT(((bits < 8 * sizeof(value)) && ! (value >> bits)) ||
+ (bits == 8 * sizeof(value)));
+
+ if ((file_buffer.bits-= (int) bits) >= 0)
{
- file_buffer.current_byte|=value << file_buffer.bits;
+ file_buffer.bitbucket|= value << file_buffer.bits;
}
else
{
- reg3 uint byte_buff;
+ reg3 ulonglong bit_buffer;
bits= (uint) -file_buffer.bits;
- DBUG_ASSERT(bits <= 8 * sizeof(value));
- byte_buff= (file_buffer.current_byte |
- ((bits != 8 * sizeof(value)) ? (uint) (value >> bits) : 0));
-#if BITS_SAVED == 32
- *file_buffer.pos++= (byte) (byte_buff >> 24) ;
- *file_buffer.pos++= (byte) (byte_buff >> 16) ;
+ bit_buffer= (file_buffer.bitbucket |
+ ((bits != 8 * sizeof(value)) ? (value >> bits) : 0));
+#if BITS_SAVED == 64
+ *file_buffer.pos++= (uchar) (bit_buffer >> 56);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 48);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 40);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 32);
#endif
- *file_buffer.pos++= (byte) (byte_buff >> 8) ;
- *file_buffer.pos++= (byte) byte_buff;
+ *file_buffer.pos++= (uchar) (bit_buffer >> 24);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 16);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 8);
+ *file_buffer.pos++= (uchar) (bit_buffer);
- DBUG_ASSERT(bits <= 8 * sizeof(ulong));
if (bits != 8 * sizeof(value))
- value&= (((ulong) 1) << bits) - 1;
-#if BITS_SAVED == 16
- if (bits >= sizeof(uint))
- {
- bits-=8;
- *file_buffer.pos++= (uchar) (value >> bits);
- value&= (1 << bits)-1;
- if (bits >= sizeof(uint))
- {
- bits-=8;
- *file_buffer.pos++= (uchar) (value >> bits);
- value&= (1 << bits)-1;
- }
- }
-#endif
+ value&= (((ulonglong) 1) << bits) - 1;
if (file_buffer.pos >= file_buffer.end)
VOID(flush_buffer(~ (ulong) 0));
file_buffer.bits=(int) (BITS_SAVED - bits);
- file_buffer.current_byte=(uint) (value << (BITS_SAVED - bits));
+ file_buffer.bitbucket= value << (BITS_SAVED - bits);
}
return;
}
/* Flush bits in bit_buffer to buffer */
-static void flush_bits (void)
+static void flush_bits(void)
{
- uint bits,byte_buff;
+ int bits;
+ ulonglong bit_buffer;
- bits=(file_buffer.bits) & ~7;
- byte_buff = file_buffer.current_byte >> bits;
- bits=BITS_SAVED - bits;
+ bits= file_buffer.bits & ~7;
+ bit_buffer= file_buffer.bitbucket >> bits;
+ bits= BITS_SAVED - bits;
while (bits > 0)
{
- bits-=8;
- *file_buffer.pos++= (byte) (uchar) (byte_buff >> bits) ;
+ bits-= 8;
+ *file_buffer.pos++= (uchar) (bit_buffer >> bits);
}
- file_buffer.bits=BITS_SAVED;
- file_buffer.current_byte=0;
- return;
+ file_buffer.bits= BITS_SAVED;
+ file_buffer.bitbucket= 0;
}
@@ -2196,3 +3064,131 @@ static int mrg_close(PACK_MRG_INFO *mrg)
my_free((gptr) mrg->file,MYF(0));
return error;
}
+
+
+#if !defined(DBUG_OFF)
+/*
+ Fake the counts to get big Huffman codes.
+
+ SYNOPSIS
+ fakebigcodes()
+ huff_counts A pointer to the counts array.
+ end_count A pointer past the counts array.
+
+ DESCRIPTION
+
+ Huffman coding works by removing the two least frequent values from
+ the list of values and add a new value with the sum of their
+ incidences in a loop until only one value is left. Every time a
+ value is reused for a new value, it gets one more bit for its
+ encoding. Hence, the least frequent values get the longest codes.
+
+ To get a maximum code length for a value, two of the values must
+ have an incidence of 1. As their sum is 2, the next infrequent value
+ must have at least an incidence of 2, then 4, 8, 16 and so on. This
+ means that one needs 2**n bytes (values) for a code length of n
+ bits. However, using more distinct values forces the use of longer
+ codes, or reaching the code length with less total bytes (values).
+
+ To get 64(32)-bit codes, I sort the counts by decreasing incidence.
+ I assign counts of 1 to the two most frequent values, a count of 2
+ for the next one, then 4, 8, and so on until 2**64-1(2**30-1). All
+ the remaining values get 1. That way every possible byte has an
+ assigned code, though not all codes are used if not all byte values
+ are present in the column.
+
+ This strategy would work with distinct column values too, but
+ requires that at least 64(32) values are present. To make things
+ easier here, I cancel all distinct column values and force byte
+ compression for all columns.
+
+ RETURN
+ void
+*/
+
+static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count)
+{
+ HUFF_COUNTS *count;
+ my_off_t *cur_count_p;
+ my_off_t *end_count_p;
+ my_off_t **cur_sort_p;
+ my_off_t **end_sort_p;
+ my_off_t *sort_counts[256];
+ my_off_t total;
+ DBUG_ENTER("fakebigcodes");
+
+ for (count= huff_counts; count < end_count; count++)
+ {
+ /*
+ Remove distinct column values.
+ */
+ if (huff_counts->tree_buff)
+ {
+ my_free((gptr) huff_counts->tree_buff, MYF(0));
+ delete_tree(&huff_counts->int_tree);
+ huff_counts->tree_buff= NULL;
+ DBUG_PRINT("fakebigcodes", ("freed distinct column values"));
+ }
+
+ /*
+ Sort counts by decreasing incidence.
+ */
+ cur_count_p= count->counts;
+ end_count_p= cur_count_p + 256;
+ cur_sort_p= sort_counts;
+ while (cur_count_p < end_count_p)
+ *(cur_sort_p++)= cur_count_p++;
+ (void) qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp);
+
+ /*
+ Assign faked counts.
+ */
+ cur_sort_p= sort_counts;
+#if SIZEOF_LONG_LONG > 4
+ end_sort_p= sort_counts + 8 * sizeof(ulonglong) - 1;
+#else
+ end_sort_p= sort_counts + 8 * sizeof(ulonglong) - 2;
+#endif
+ /* Most frequent value gets a faked count of 1. */
+ **(cur_sort_p++)= 1;
+ total= 1;
+ while (cur_sort_p < end_sort_p)
+ {
+ **(cur_sort_p++)= total;
+ total<<= 1;
+ }
+ /* Set the last value. */
+ **(cur_sort_p++)= --total;
+ /*
+ Set the remaining counts.
+ */
+ end_sort_p= sort_counts + 256;
+ while (cur_sort_p < end_sort_p)
+ **(cur_sort_p++)= 1;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Compare two counts for reverse sorting.
+
+ SYNOPSIS
+ fakecmp()
+ count1 One count.
+ count2 Another count.
+
+ RETURN
+ 1 count1 < count2
+ 0 count1 == count2
+ -1 count1 > count2
+*/
+
+static int fakecmp(my_off_t **count1, my_off_t **count2)
+{
+ return ((**count1 < **count2) ? 1 :
+ (**count1 > **count2) ? -1 : 0);
+}
+#endif
+
+
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index 3a59a060778..f8e1d99bfab 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -88,9 +88,16 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib
$(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib
-std_data/%.pem:
+std_data/client-key.pem:
+ @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
+std_data/client-cert.pem:
+ @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
+std_data/cacert.pem:
+ @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
+std_data/server-cert.pem:
+ @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
+std_data/server-key.pem:
@CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
-
SUFFIXES = .sh
diff --git a/mysql-test/README b/mysql-test/README
index 65e6186613a..10d64784ed4 100644
--- a/mysql-test/README
+++ b/mysql-test/README
@@ -2,8 +2,17 @@ This directory contains a test suite for mysql daemon. To run
the currently existing test cases, simply execute ./mysql-test-run in
this directory. It will fire up the newly built mysqld and test it.
-If you want to run the test with a running MySQL server use the --external
-option to mysql-test-run.
+If you want to run a test with a running MySQL server use the --extern
+option to mysql-test-run. Please note that in this mode the test suite
+expects user to specify test names to run. Otherwise it falls back to the
+normal "non-extern" behaviour. The reason is that some tests
+could not run with external server. Here is the sample command
+to test "alias" and "analyze" tests on external server:
+
+mysql-test-run --extern alias analyze
+
+To match your setup you might also need to provide --socket, --user and
+other relevant options.
Note that you do not have to have to do make install, and you could
actually have a co-existing MySQL installation - the tests will not
diff --git a/mysql-test/include/not_openssl.inc b/mysql-test/include/not_openssl.inc
new file mode 100644
index 00000000000..afe2ed37c28
--- /dev/null
+++ b/mysql-test/include/not_openssl.inc
@@ -0,0 +1,4 @@
+-- require r/not_openssl.require
+disable_query_log;
+show variables like "have_openssl";
+enable_query_log;
diff --git a/mysql-test/include/ps_create.inc b/mysql-test/include/ps_create.inc
index 306ed3f1cac..b2a6fc4b920 100644
--- a/mysql-test/include/ps_create.inc
+++ b/mysql-test/include/ps_create.inc
@@ -33,7 +33,7 @@ eval create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
+ c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
diff --git a/mysql-test/include/ps_query.inc b/mysql-test/include/ps_query.inc
index 63504a0fa2b..27a86f88231 100644
--- a/mysql-test/include/ps_query.inc
+++ b/mysql-test/include/ps_query.inc
@@ -300,7 +300,7 @@ set @arg00=1;
prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
-prepare stmt1 from ' select a,b from t1 limit ? ';
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
execute stmt1 using @arg00;
##### parameter used in many places
diff --git a/mysql-test/include/rpl_stmt_seq.inc b/mysql-test/include/rpl_stmt_seq.inc
new file mode 100644
index 00000000000..3c91505d0d6
--- /dev/null
+++ b/mysql-test/include/rpl_stmt_seq.inc
@@ -0,0 +1,201 @@
+# include/rpl_stmt_seq.inc
+#
+# Please be very careful when editing this routine, because the handling of
+# the $variables is extreme sensitive.
+#
+
+###############################################################
+# Debug options : To debug this test script
+###############################################################
+let $show_binlog= 0;
+let $manipulate= 1;
+
+######## The typical test sequence
+# 1. INSERT without commit
+# check table content of master and slave
+# 2. EXECUTE the statement
+# check table content of master and slave
+# 3. ROLLBACK
+# check table content of master and slave
+# 4. flush the logs
+
+let $VERSION=`select version()`;
+
+--disable_query_log
+# SELECT '######## new test sequence ########' as "";
+eval SELECT CONCAT('######## ','$my_stmt',' ########') as "";
+--enable_query_log
+
+
+###############################################################
+# Predict the number of the current log
+###############################################################
+# Disable the logging of the log number computation.
+--disable_query_log
+# $_log_num_n should contain the number of the current binlog in numeric style.
+# If this routine is called for the first time, $_log_num will not initialized
+# and contain the value '' instead of '1'. So we will correct it here.
+#
+eval set @aux= IF('$_log_num_n' = '', '1', '$_log_num_n');
+let $_log_num_n= `SELECT @aux`;
+eval set @aux= LPAD('$_log_num_n',6,'0');
+# SELECT @aux AS "@aux is";
+#
+# $_log_num_s should contain the number of the current binlog in string style.
+let $_log_num_s= `select @aux`;
+# eval SELECT '$log_num' ;
+--enable_query_log
+
+###############################################################
+# INSERT
+###############################################################
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+# Maybe it would be smarter to use a table with autoincrement column.
+let $MAX= `SELECT MAX(f1) FROM t1` ;
+eval INSERT INTO t1 SET f1= $MAX + 1;
+# results before DDL(to be tested)
+SELECT MAX(f1) FROM t1;
+if ($show_binlog)
+{
+--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+eval SHOW BINLOG EVENTS IN 'master-bin.$_log_num_s';
+}
+sync_slave_with_master;
+
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+# results before DDL(to be tested)
+SELECT MAX(f1) FROM t1;
+if ($show_binlog)
+{
+--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+eval SHOW BINLOG EVENTS IN 'slave-bin.$_log_num_s';
+}
+
+###############################################################
+# command to be tested
+###############################################################
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+eval $my_stmt;
+# Devaluate $my_stmt, to detect script bugs
+let $my_stmt= ERROR: YOU FORGOT TO FILL IN THE STATEMENT;
+# results after DDL(to be tested)
+SELECT MAX(f1) FROM t1;
+if ($show_binlog)
+{
+--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+eval SHOW BINLOG EVENTS IN 'master-bin.$_log_num_s';
+}
+sync_slave_with_master;
+
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+# results after DDL(to be tested)
+SELECT MAX(f1) FROM t1;
+if ($show_binlog)
+{
+--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+eval SHOW BINLOG EVENTS IN 'slave-bin.$_log_num_s';
+}
+
+###############################################################
+# ROLLBACK
+###############################################################
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+ROLLBACK;
+# results after final ROLLBACK
+SELECT MAX(f1) FROM t1;
+# Try to detect if the DDL command caused that the INSERT is committed
+# $MAX holds the highest/last value just before the insert of MAX + 1
+--disable_query_log
+eval SELECT CONCAT(CONCAT('TEST-INFO: MASTER: The INSERT is ',
+ IF(MAX(f1) = $MAX + 1, 'committed', 'not committed')),
+ IF((MAX(f1) = $MAX + 1) XOR NOT $my_master_commit,
+ ' (Succeeded)',
+ ' (Failed)')) AS ""
+ FROM mysqltest1.t1;
+--enable_query_log
+if ($show_binlog)
+{
+--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+eval SHOW BINLOG EVENTS IN 'master-bin.$_log_num_s';
+}
+sync_slave_with_master;
+
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+# results after final ROLLBACK
+SELECT MAX(f1) FROM t1;
+--disable_query_log
+eval SELECT CONCAT(CONCAT('TEST-INFO: SLAVE: The INSERT is ',
+ IF(MAX(f1) = $MAX + 1, 'committed', 'not committed')),
+ IF((MAX(f1) = $MAX + 1) XOR NOT $my_slave_commit,
+ ' (Succeeded)',
+ ' (Failed)')) AS ""
+ FROM mysqltest1.t1;
+--enable_query_log
+if ($show_binlog)
+{
+--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+eval SHOW BINLOG EVENTS IN 'slave-bin.$_log_num_s';
+}
+
+###############################################################
+# Manipulate binlog
+###############################################################
+if ($manipulate)
+{
+#### Manipulate the binary logs,
+# so that the output of SHOW BINLOG EVENTS IN <current log>
+# contains only commands of the current test sequence.
+# - flush the master and the slave log
+# ---> both start to write into new logs with incremented number
+# - increment $_log_num_n
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+flush logs;
+# sleep 1;
+# eval SHOW BINLOG EVENTS IN 'master-bin.$_log_num_s';
+sync_slave_with_master;
+
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+# the final content of the binary log
+flush logs;
+# The next sleep is urgent needed.
+# Without this sleep the slaves crashes often, when the SHOW BINLOG
+# is executed. :-(
+# sleep 1;
+# eval SHOW BINLOG EVENTS IN 'slave-bin.$_log_num_s';
+inc $_log_num_n;
+}
+
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
diff --git a/mysql-test/include/show_msg.inc b/mysql-test/include/show_msg.inc
index 5a29541edcf..659dce14686 100755
--- a/mysql-test/include/show_msg.inc
+++ b/mysql-test/include/show_msg.inc
@@ -6,13 +6,19 @@
# Usage:
# Add the following to any *.test file:
# :
-# set @message="This is a message example";
+# let $message= <value>;
# --source include/show_msg.inc
# :
#
+# Attention:
+# - Please do not write any spaces between $message and the "=", because the
+# assignment will not work.
+# - Be careful with single quotes. They must be escaped like "''" or "\'".
+#
+# "include/show_msg80.inc" contains a detailed description and examples.
--disable_query_log
-SET @utf8_message = CONVERT(@message using utf8);
+eval SET @utf8_message = CONVERT('$message' using utf8);
select @utf8_message as ""
union
select repeat(CONVERT('-' using utf8),char_length(@utf8_message));
diff --git a/mysql-test/include/show_msg80.inc b/mysql-test/include/show_msg80.inc
index d9a59c5517a..42fb35edbcc 100755
--- a/mysql-test/include/show_msg80.inc
+++ b/mysql-test/include/show_msg80.inc
@@ -1,22 +1,117 @@
#### include/show_msg80.inc
#
-# This file writes the value set in @message into the
-# a protocol file as part of executing a test sequence
-# with a dash line that is fixed on 80 characters.
-# This can be used in the case of long messages,
-# multi line messages that exceed 80 or if an 80 char
-# line is desired for short messages.
+# This file writes the value set in @message into the a protocol file as part
+# of executing a test sequence with a dash line that is fixed on 80 characters.
+#
+# This can be used in the case of long messages, multi line messages that
+# exceed 80 or if an 80 char line is desired for short messages.
#
# Usage:
# Add the following to any *.test file:
# :
-# set @message="This is a message example";
+# let $message= <value>;
# --source include/show_msg80.inc
# :
#
+# Attention:
+# - Please do not write any spaces between $message and the "=", because the
+# assignment will not work.
+# - Be careful with single quotes within the value. They must be escaped like
+# "''" or "\'".
+# - Do not keep the value between single quotes.
+#
+#
+# Content of "$message" and protocol output depending on the assignment:
+# ----------------------------------------------------------------------
+#
+# I is assumed, that the value is not kept between double quotes.
+#
+# <x> first character after "$message=",
+# where the content is not (space or tab)
+# <y*> first character after beginning of the line,
+# where the content is not (space or tab)
+# <z> last char before ";"
+# | beginning or end of line
+#
+# script: let $message= <x><whatever0>|
+# | <y1><whatever1>|
+# |................|
+# | <yn><whatevern><z>;
+# content: "<x><whatever0><new line><y1><whatever1><new line>
+# ....<new line><yn><whatevern><z>"
+# protocol output: |<x><whatever0>|
+# |<y1><whatever1>|
+# |.....|
+# |<yn><whatevern><z>|
+# |--- 80 dashes ---|
+#
+# Attention:
+# <x> and <y*> set to characters like "-$#" which are also used
+# to start comments, options and the names of mysqltest variables
+# lead to syntax errors or mangled messages.
+#
+#
+# Examples of messages:
+# ---------------------
+#
+# Variant1 (ease of use):
+# Several lines with indentation kept between double quotes
+# script: |let $message=
+# |" Testcase 3.1 : Ensure that Pi is not an|
+# | integer number.|
+# | Third line";
+# protocol: |" Testcase 3.1 : Ensure that Pi is not an|
+# | integer number.|
+# | Third line"|
+# |------ 80 dashes ----|
+#
+# Please mention that
+# - the '"' preserves the indentation.
+# - it is easy to write the script lines to get a fine indentation,
+# if the value starts at the beginning of a new line
+# - the '"' is printed
+# - there are the least or no problems with characters like "-#$"
+#
+#
+# Variant 2 (grep the messages from the protocol is easy):
+# Several lines with indentation + auxiliary character (".")
+# at the (non tab or space) beginning of every message line
+# script: |let $message= . Testcase 3.1 : Ensure that Pi is not an|
+# | . integer number.|
+# | . Third line;
+# protocol: |. Testcase 3.1 : Ensure that Pi is not an|
+# |. integer number.|
+# |. Third line|
+# |------ 80 dashes ----|
+# Please mention that
+# - the auxiliary character preserves the indentation.
+# - it is easy to write the script lines to get a fine indentation
+# - the auxiliary character is printed
+# - it is recommended to use "." as auxiliary character
+# - auxiliary characters like "-'$#" cause problems
+#
+#
+#
+# Bad variant1: Several lines with lost indentation
+# script: |let $message= Here is message line 1
+# | message line 2;
+# protocol: |Here is message line 1|
+# |message line 2|
+# |------ 80 dashes ----|
+# Please mention, that the leading spaces of the message lines disappeared.
+#
+# Bad variant2: Several lines leading to a syntax error, because of "-"
+# script: |let $message= - This is a message
+# | - with a second and
+# | - third line;
+# protocol: | - third line;;
+# |ERROR 42000: You have an error ... near '- third line'
+# + several following errors
+#
+#
--disable_query_log
-SET @utf8_message = CONVERT(@message using utf8);
+eval SET @utf8_message = CONVERT('$message' using utf8);
select @utf8_message as ""
union
select repeat(CONVERT('-' using utf8),80);
diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl
index 878afe95f2c..2babaabc24c 100644
--- a/mysql-test/lib/mtr_cases.pl
+++ b/mysql-test/lib/mtr_cases.pl
@@ -4,6 +4,7 @@
# and is part of the translation of the Bourne shell script with the
# same name.
+use File::Basename;
use strict;
sub collect_test_cases ($);
@@ -39,6 +40,7 @@ sub collect_test_cases ($) {
if ( @::opt_cases )
{
foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort
+ $tname= basename($tname, ".test");
my $elem= "$tname.test";
if ( ! -f "$testdir/$elem")
{
@@ -126,16 +128,6 @@ sub collect_one_test_case($$$$$) {
return;
}
- # FIXME temporary solution, we have a hard coded list of test cases to
- # skip if we are using the embedded server
-
- if ( $::glob_use_embedded_server and
- mtr_match_any_exact($tname,\@::skip_if_embedded_server) )
- {
- $tinfo->{'skip'}= 1;
- return;
- }
-
# ----------------------------------------------------------------------
# Collect information about test case
# ----------------------------------------------------------------------
@@ -162,6 +154,14 @@ sub collect_one_test_case($$$$$) {
}
}
+ if ( defined mtr_match_prefix($tname,"federated") )
+ {
+ $tinfo->{'slave_num'}= 1; # Default, use one slave
+
+ # FIXME currently we always restart slaves
+ $tinfo->{'slave_restart'}= 1;
+ }
+
# FIXME what about embedded_server + ndbcluster, skip ?!
my $master_opt_file= "$testdir/$tname-master.opt";
@@ -171,54 +171,73 @@ sub collect_one_test_case($$$$$) {
my $slave_sh= "$testdir/$tname-slave.sh";
my $disabled= "$testdir/$tname.disabled";
- $tinfo->{'master_opt'}= [];
- $tinfo->{'slave_opt'}= [];
+ $tinfo->{'master_opt'}= $::glob_win32 ? ["--default-time-zone=+3:00"] : [];
+ $tinfo->{'slave_opt'}= $::glob_win32 ? ["--default-time-zone=+3:00"] : [];
$tinfo->{'slave_mi'}= [];
if ( -f $master_opt_file )
{
$tinfo->{'master_restart'}= 1; # We think so for now
- # This is a dirty hack from old mysql-test-run, we use the opt file
- # to flag other things as well, it is not a opt list at all
- my $extra_master_opt= mtr_get_opts_from_file($master_opt_file);
- foreach my $opt (@$extra_master_opt)
+ MASTER_OPT:
{
- my $value;
-
- $value= mtr_match_prefix($opt, "--timezone=");
+ my $master_opt= mtr_get_opts_from_file($master_opt_file);
- if ( defined $value )
+ foreach my $opt ( @$master_opt )
{
- $tinfo->{'timezone'}= $value;
- $extra_master_opt= [];
- $tinfo->{'master_restart'}= 0;
- last;
- }
+ my $value;
- $value= mtr_match_prefix($opt, "--result-file=");
+ # This is a dirty hack from old mysql-test-run, we use the opt
+ # file to flag other things as well, it is not a opt list at
+ # all
- if ( defined $value )
- {
- $tinfo->{'result_file'}= "r/$value.result";
- if ( $::opt_result_ext and $::opt_record or
- -f "$tinfo->{'result_file'}$::opt_result_ext")
+ $value= mtr_match_prefix($opt, "--timezone=");
+ if ( defined $value )
+ {
+ $tinfo->{'timezone'}= $value;
+ $tinfo->{'skip'}= 1 if $::glob_win32; # FIXME server unsets TZ
+ last MASTER_OPT;
+ }
+
+ $value= mtr_match_prefix($opt, "--result-file=");
+ if ( defined $value )
+ {
+ $tinfo->{'result_file'}= "r/$value.result";
+ if ( $::opt_result_ext and $::opt_record or
+ -f "$tinfo->{'result_file'}$::opt_result_ext")
+ {
+ $tinfo->{'result_file'}.= $::opt_result_ext;
+ }
+ $tinfo->{'master_restart'}= 0;
+ last MASTER_OPT;
+ }
+
+ # If we set default time zone, remove the one we have
+ $value= mtr_match_prefix($opt, "--default-time-zone=");
+ if ( defined $value )
{
- $tinfo->{'result_file'}.= $::opt_result_ext;
+ $tinfo->{'master_opt'}= [];
}
- $extra_master_opt= [];
- $tinfo->{'master_restart'}= 0;
- last;
+
}
- }
- $tinfo->{'master_opt'}= $extra_master_opt;
+ # Ok, this was a real option list, add it
+ push(@{$tinfo->{'master_opt'}}, @$master_opt);
+ }
}
if ( -f $slave_opt_file )
{
- $tinfo->{'slave_opt'}= mtr_get_opts_from_file($slave_opt_file);
$tinfo->{'slave_restart'}= 1;
+ my $slave_opt= mtr_get_opts_from_file($slave_opt_file);
+
+ foreach my $opt ( @$slave_opt )
+ {
+ # If we set default time zone, remove the one we have
+ my $value= mtr_match_prefix($opt, "--default-time-zone=");
+ $tinfo->{'slave_opt'}= [] if defined $value;
+ }
+ push(@{$tinfo->{'slave_opt'}}, @$slave_opt);
}
if ( -f $slave_mi_file )
diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl
index efa1b3bec21..aba6f78c9de 100644
--- a/mysql-test/lib/mtr_misc.pl
+++ b/mysql-test/lib/mtr_misc.pl
@@ -9,6 +9,9 @@ use strict;
sub mtr_full_hostname ();
sub mtr_init_args ($);
sub mtr_add_arg ($$);
+sub mtr_path_exists(@);
+sub mtr_script_exists(@);
+sub mtr_exe_exists(@);
##############################################################################
#
@@ -47,4 +50,53 @@ sub mtr_add_arg ($$) {
push(@$args, sprintf($format, @fargs));
}
+##############################################################################
+
+sub mtr_path_exists (@) {
+ foreach my $path ( @_ )
+ {
+ return $path if -e $path;
+ }
+ if ( @_ == 1 )
+ {
+ mtr_error("Could not find $_[0]");
+ }
+ else
+ {
+ mtr_error("Could not find any of " . join(" ", @_));
+ }
+}
+
+sub mtr_script_exists (@) {
+ foreach my $path ( @_ )
+ {
+ return $path if -x $path;
+ }
+ if ( @_ == 1 )
+ {
+ mtr_error("Could not find $_[0]");
+ }
+ else
+ {
+ mtr_error("Could not find any of " . join(" ", @_));
+ }
+}
+
+sub mtr_exe_exists (@) {
+ foreach my $path ( @_ )
+ {
+ $path.= ".exe" if $::opt_win32;
+ return $path if -x $path;
+ }
+ if ( @_ == 1 )
+ {
+ mtr_error("Could not find $_[0]");
+ }
+ else
+ {
+ mtr_error("Could not find any of " . join(" ", @_));
+ }
+}
+
+
1;
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index 7bca422773c..1eb4f6b7c58 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -669,6 +669,8 @@ sub mtr_mysqladmin_shutdown () {
last; # If we got here, we are done
}
+ sleep(5) if $::glob_win32; # FIXME next startup fails if no sleep
+
return $res;
}
diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl
index a258d139bb1..0af34d11a3f 100644
--- a/mysql-test/lib/mtr_report.pl
+++ b/mysql-test/lib/mtr_report.pl
@@ -38,6 +38,13 @@ sub mtr_show_failed_diff ($) {
my $result_file= "r/$tname.result";
my $eval_file= "r/$tname.eval";
+ if ( $::opt_suite ne "main" )
+ {
+ $reject_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$reject_file";
+ $result_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$result_file";
+ $eval_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$eval_file";
+ }
+
if ( -f $eval_file )
{
$result_file= $eval_file;
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 0394c7abc9e..74d1a8dc6f2 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -100,31 +100,6 @@ require "lib/mtr_misc.pl";
$Devel::Trace::TRACE= 1;
-my @skip_if_embedded_server=
- (
- "alter_table",
- "bdb-deadlock",
- "connect",
- "flush_block_commit",
- "grant2",
- "grant_cache",
- "grant",
- "init_connect",
- "innodb-deadlock",
- "innodb-lock",
- "mix_innodb_myisam_binlog",
- "mysqlbinlog2",
- "mysqlbinlog",
- "mysqldump",
- "mysql_protocols",
- "ps_1general",
- "rename",
- "show_check",
- "system_mysql_db_fix",
- "user_var",
- "variables",
- );
-
# Used by gcov
our @mysqld_src_dirs=
(
@@ -196,6 +171,7 @@ our $exe_mysqlbinlog;
our $exe_mysql_client_test;
our $exe_mysqld;
our $exe_mysqldump; # Called from test case
+our $exe_mysqlshow; # Called from test case
our $exe_mysql_fix_system_tables;
our $exe_mysqltest;
our $exe_slave_mysqld;
@@ -204,7 +180,7 @@ our $opt_bench= 0;
our $opt_small_bench= 0;
our $opt_big_test= 0; # Send --big-test to mysqltest
-our $opt_extra_mysqld_opt; # FIXME not handled
+our @opt_extra_mysqld_opt;
our $opt_compress;
our $opt_current_test;
@@ -241,6 +217,7 @@ our $opt_ndbcluster_port;
our $opt_ndbconnectstring;
our $opt_no_manager; # Does nothing now, we never use manager
+our $opt_manager_port; # Does nothing now, we never use manager
our $opt_old_master;
@@ -287,6 +264,7 @@ our $opt_warnings;
our $opt_udiff;
+our $opt_skip_ndbcluster;
our $opt_with_ndbcluster;
our $opt_with_openssl;
@@ -325,7 +303,7 @@ sub mysqld_arguments ($$$$$);
sub stop_masters_slaves ();
sub stop_masters ();
sub stop_slaves ();
-sub run_mysqltest ($$);
+sub run_mysqltest ($);
sub usage ($);
######################################################################
@@ -468,9 +446,9 @@ sub command_line_setup () {
# These are defaults for things that are set on the command line
$opt_suite= "main"; # Special default suite
- my $opt_master_myport= 9306;
- my $opt_slave_myport= 9308;
- $opt_ndbcluster_port= 9350;
+ my $opt_master_myport= 9306;
+ my $opt_slave_myport= 9308;
+ $opt_ndbcluster_port= 9350;
# Read the command line
# Note: Keep list, and the order, in sync with usage at end of this file
@@ -481,11 +459,12 @@ sub command_line_setup () {
'ps-protocol' => \$opt_ps_protocol,
'bench' => \$opt_bench,
'small-bench' => \$opt_small_bench,
- 'no-manager' => \$opt_no_manager,
+ 'no-manager' => \$opt_no_manager, # Currently not used
# Control what test suites or cases to run
'force' => \$opt_force,
'with-ndbcluster' => \$opt_with_ndbcluster,
+ 'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
'do-test=s' => \$opt_do_test,
'suite=s' => \$opt_suite,
'skip-rpl' => \$opt_skip_rpl,
@@ -495,12 +474,13 @@ sub command_line_setup () {
'master_port=i' => \$opt_master_myport,
'slave_port=i' => \$opt_slave_myport,
'ndbcluster_port=i' => \$opt_ndbcluster_port,
+ 'manager-port=i' => \$opt_manager_port, # Currently not used
# Test case authoring
'record' => \$opt_record,
# ???
- 'mysqld=s' => \$opt_extra_mysqld_opt,
+ 'mysqld=s' => \@opt_extra_mysqld_opt,
# Run test on running server
'extern' => \$opt_extern,
@@ -684,6 +664,11 @@ sub command_line_setup () {
$opt_ndbconnectstring= "host=localhost:$opt_ndbcluster_port";
}
+ if ( $opt_skip_ndbcluster )
+ {
+ $opt_with_ndbcluster= 0;
+ }
+
# FIXME
#if ( $opt_valgrind or $opt_valgrind_all )
@@ -785,137 +770,84 @@ sub executable_setup () {
if ( $opt_source_dist )
{
- if ( $glob_use_embedded_server )
- {
- if ( -f "$glob_basedir/libmysqld/examples/mysqltest" )
- {
- $exe_mysqltest= "$glob_basedir/libmysqld/examples/mysqltest";
- }
- else
- {
- mtr_error("Can't find embedded server 'mysqltest'");
- }
- $exe_mysql_client_test=
- "$glob_basedir/libmysqld/examples/mysql_client_test_embedded";
- }
- else
- {
- if ( -f "$glob_basedir/client/.libs/lt-mysqltest" )
- {
- $exe_mysqltest= "$glob_basedir/client/.libs/lt-mysqltest";
- }
- elsif ( -f "$glob_basedir/client/.libs/mysqltest" )
- {
- $exe_mysqltest= "$glob_basedir/client/.libs/mysqltest";
- }
- else
- {
- $exe_mysqltest= "$glob_basedir/client/mysqltest";
- }
- $exe_mysql_client_test=
- "$glob_basedir/tests/mysql_client_test";
- }
- if ( -f "$glob_basedir/client/.libs/mysqldump" )
+ if ( $glob_win32 )
{
- $exe_mysqldump= "$glob_basedir/client/.libs/mysqldump";
+ $path_client_bindir= mtr_path_exists("$glob_basedir/client_release",
+ "$glob_basedir/bin");
+ $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt");
+ $path_language= mtr_path_exists("$glob_basedir/share/english/");
+ $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets");
}
else
{
- $exe_mysqldump= "$glob_basedir/client/mysqldump";
+ $path_client_bindir= mtr_path_exists("$glob_basedir/client");
+ $exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld");
+ $path_language= mtr_path_exists("$glob_basedir/sql/share/english/");
+ $path_charsetsdir= mtr_path_exists("$glob_basedir/sql/share/charsets");
}
- if ( -f "$glob_basedir/client/.libs/mysqlbinlog" )
+
+ if ( $glob_use_embedded_server )
{
- $exe_mysqlbinlog= "$glob_basedir/client/.libs/mysqlbinlog";
+ my $path_examples= "$glob_basedir/libmysqld/examples";
+ $exe_mysqltest= mtr_exe_exists("$path_examples/mysqltest");
+ $exe_mysql_client_test=
+ mtr_exe_exists("$path_examples/mysql_client_test_embedded");
}
else
{
- $exe_mysqlbinlog= "$glob_basedir/client/mysqlbinlog";
+ $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
+ $exe_mysql_client_test=
+ mtr_exe_exists("$glob_basedir/tests/mysql_client_test");
}
-
- $path_client_bindir= "$glob_basedir/client";
- $exe_mysqld= "$glob_basedir/sql/mysqld";
- $exe_mysqladmin= "$path_client_bindir/mysqladmin";
- $exe_mysql= "$path_client_bindir/mysql";
- $exe_mysql_fix_system_tables= "$glob_basedir/scripts/mysql_fix_privilege_tables";
- $path_language= "$glob_basedir/sql/share/english/";
- $path_charsetsdir= "$glob_basedir/sql/share/charsets";
-
- $path_ndb_tools_dir= "$glob_basedir/ndb/tools";
- $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm";
+ $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
+ $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
+ $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
+ $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
+ $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
+ $exe_mysql_fix_system_tables=
+ mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables");
+ $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools");
+ $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm";
}
else
{
- my $path_tests_bindir= "$glob_basedir/tests";
-
- $path_client_bindir= "$glob_basedir/bin";
- $exe_mysqltest= "$path_client_bindir/mysqltest";
- $exe_mysqldump= "$path_client_bindir/mysqldump";
- $exe_mysqlbinlog= "$path_client_bindir/mysqlbinlog";
- $exe_mysqladmin= "$path_client_bindir/mysqladmin";
- $exe_mysql= "$path_client_bindir/mysql";
- $exe_mysql_fix_system_tables= "$path_client_bindir/scripts/mysql_fix_privilege_tables";
-
- if ( -d "$glob_basedir/share/mysql/english" )
- {
- $path_language ="$glob_basedir/share/mysql/english/";
- $path_charsetsdir ="$glob_basedir/share/mysql/charsets";
- }
- else
- {
- $path_language ="$glob_basedir/share/english/";
- $path_charsetsdir ="$glob_basedir/share/charsets";
- }
-
- if ( -x "$glob_basedir/libexec/mysqld" )
- {
- $exe_mysqld= "$glob_basedir/libexec/mysqld";
- }
- else
- {
- $exe_mysqld= "$glob_basedir/bin/mysqld";
- }
+ $path_client_bindir= mtr_path_exists("$glob_basedir/bin");
+ $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
+ $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
+ $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
+ $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
+ $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
+ $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
+ $exe_mysql_fix_system_tables=
+ mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables");
+
+ $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/",
+ "$glob_basedir/share/english/");
+ $path_charsetsdir= mtr_path_exists("$glob_basedir/share/mysql/charsets",
+ "$glob_basedir/share/charsets");
+ $exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld",
+ "$glob_basedir/bin/mysqld");
if ( $glob_use_embedded_server )
{
- if ( -f "$path_client_bindir/mysqltest_embedded" )
- {
- # FIXME valgrind?
- $exe_mysqltest="$path_client_bindir/mysqltest_embedded";
- }
- else
- {
- mtr_error("Cannot find embedded server 'mysqltest_embedded'");
- }
- if ( -d "$path_tests_bindir/mysql_client_test_embedded" )
- {
- $exe_mysql_client_test=
- "$path_tests_bindir/mysql_client_test_embedded";
- }
- else
- {
- $exe_mysql_client_test=
- "$path_client_bindir/mysql_client_test_embedded";
- }
+ $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest_embedded");
+ $exe_mysql_client_test=
+ mtr_exe_exists("$glob_basedir/tests/mysql_client_test_embedded",
+ "$path_client_bindir/mysql_client_test_embedded");
}
else
{
- $exe_mysqltest="$path_client_bindir/mysqltest";
- $exe_mysql_client_test="$path_client_bindir/mysql_client_test";
+ $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
+ $exe_mysql_client_test=
+ mtr_exe_exists("$path_client_bindir/mysql_client_test");
}
$path_ndb_tools_dir= "$glob_basedir/bin";
$exe_ndb_mgm= "$glob_basedir/bin/ndb_mgm";
}
- if ( ! $exe_master_mysqld )
- {
- $exe_master_mysqld= $exe_mysqld;
- }
-
- if ( ! $exe_slave_mysqld )
- {
- $exe_slave_mysqld= $exe_mysqld;
- }
+ $exe_master_mysqld= $exe_master_mysqld || $exe_mysqld;
+ $exe_slave_mysqld= $exe_slave_mysqld || $exe_mysqld;
$path_ndb_backup_dir=
"$opt_vardir/ndbcluster-$opt_ndbcluster_port";
@@ -934,15 +866,19 @@ sub executable_setup () {
sub environment_setup () {
# --------------------------------------------------------------------------
- # Set LD_LIBRARY_PATH if we are using shared libraries
+ # We might not use a standard installation directory, like /usr/lib.
+ # Set LD_LIBRARY_PATH to make sure we find our installed libraries.
# --------------------------------------------------------------------------
- $ENV{'LD_LIBRARY_PATH'}=
- "$glob_basedir/lib:$glob_basedir/libmysql/.libs" .
- ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : "");
- $ENV{'DYLD_LIBRARY_PATH'}=
- "$glob_basedir/lib:$glob_basedir/libmysql/.libs" .
- ($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : "");
+ unless ( $opt_source_dist )
+ {
+ $ENV{'LD_LIBRARY_PATH'}=
+ "$glob_basedir/lib" .
+ ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : "");
+ $ENV{'DYLD_LIBRARY_PATH'}=
+ "$glob_basedir/lib" .
+ ($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : "");
+ }
# --------------------------------------------------------------------------
# Also command lines in .opt files may contain env vars
@@ -953,13 +889,25 @@ sub environment_setup () {
$ENV{'LC_COLLATE'}= "C";
$ENV{'USE_RUNNING_SERVER'}= $glob_use_running_server;
$ENV{'MYSQL_TEST_DIR'}= $glob_mysql_test_dir;
+ $ENV{'MYSQL_TEST_WINDIR'}= $glob_mysql_test_dir;
$ENV{'MASTER_MYSOCK'}= $master->[0]->{'path_mysock'};
+ $ENV{'MASTER_WINMYSOCK'}= $master->[0]->{'path_mysock'};
$ENV{'MASTER_MYSOCK1'}= $master->[1]->{'path_mysock'};
$ENV{'MASTER_MYPORT'}= $master->[0]->{'path_myport'};
$ENV{'MASTER_MYPORT1'}= $master->[1]->{'path_myport'};
$ENV{'SLAVE_MYPORT'}= $slave->[0]->{'path_myport'};
# $ENV{'MYSQL_TCP_PORT'}= '@MYSQL_TCP_PORT@'; # FIXME
$ENV{'MYSQL_TCP_PORT'}= 3306;
+
+ if ( $glob_cygwin_perl )
+ {
+ foreach my $key ('MYSQL_TEST_WINDIR','MASTER_MYSOCK')
+ {
+ $ENV{$key}= `cygpath -w $ENV{$key}`;
+ $ENV{$key} =~ s,\\,\\\\,g;
+ chomp($ENV{$key});
+ }
+ }
}
@@ -1021,11 +969,6 @@ sub kill_and_cleanup () {
mtr_report("Removing Stale Files");
- if ( -l $opt_vardir and ! unlink($opt_vardir) )
- {
- mtr_error("Can't remove soft link \"$opt_vardir\"");
- }
-
rmtree("$opt_vardir/log");
rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port");
rmtree("$opt_vardir/run");
@@ -1399,10 +1342,11 @@ sub run_testcase ($) {
if ( ! $glob_use_running_server and ! $glob_use_embedded_server )
{
- if ( $tinfo->{'master_restart'} or $master->[0]->{'uses_special_flags'} )
+ if ( $tinfo->{'master_restart'} or
+ $master->[0]->{'running_master_is_special'} )
{
stop_masters();
- $master->[0]->{'uses_special_flags'}= 0; # Forget about why we stopped
+ $master->[0]->{'running_master_is_special'}= 0; # Forget why we stopped
}
# ----------------------------------------------------------------------
@@ -1480,9 +1424,9 @@ sub run_testcase ($) {
}
}
- if ( @{$tinfo->{'master_opt'}} )
+ if ( $tinfo->{'master_restart'} )
{
- $master->[0]->{'uses_special_flags'}= 1;
+ $master->[0]->{'running_master_is_special'}= 1;
}
}
@@ -1529,7 +1473,7 @@ sub run_testcase ($) {
}
unlink($path_timefile);
- my $res= run_mysqltest($tinfo, $tinfo->{'master_opt'});
+ my $res= run_mysqltest($tinfo);
if ( $res == 0 )
{
@@ -1610,11 +1554,12 @@ sub do_before_start_master ($$) {
}
}
+ # FIXME only remove the ones that are tied to this master
# Remove old master.info and relay-log.info files
- unlink("$opt_vardir/master-data/master.info");
- unlink("$opt_vardir/master-data/relay-log.info");
- unlink("$opt_vardir/master1-data/master.info");
- unlink("$opt_vardir/master1-data/relay-log.info");
+ unlink("$master->[0]->{'path_myddir'}/master.info");
+ unlink("$master->[0]->{'path_myddir'}/relay-log.info");
+ unlink("$master->[1]->{'path_myddir'}/master.info");
+ unlink("$master->[1]->{'path_myddir'}/relay-log.info");
# Run master initialization shell script if one exists
if ( $init_script )
@@ -1708,24 +1653,37 @@ sub mysqld_arguments ($$$$$) {
if ( $type eq 'master' )
{
- mtr_add_arg($args, "%s--log-bin=%s/log/master-bin", $prefix, $opt_vardir);
+ my $id= $idx > 0 ? $idx + 101 : 1;
+
+ mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix,
+ $opt_vardir, $sidx);
mtr_add_arg($args, "%s--pid-file=%s", $prefix,
$master->[$idx]->{'path_mypid'});
mtr_add_arg($args, "%s--port=%d", $prefix,
$master->[$idx]->{'path_myport'});
- mtr_add_arg($args, "%s--server-id=1", $prefix);
+ mtr_add_arg($args, "%s--server-id=%d", $prefix, $id);
mtr_add_arg($args, "%s--socket=%s", $prefix,
$master->[$idx]->{'path_mysock'});
- mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:50M", $prefix);
+ mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:128M:autoextend", $prefix);
mtr_add_arg($args, "%s--local-infile", $prefix);
mtr_add_arg($args, "%s--datadir=%s", $prefix,
$master->[$idx]->{'path_myddir'});
+
+ if ( $idx > 0 )
+ {
+ mtr_add_arg($args, "%s--skip-innodb", $prefix);
+ }
+
+ if ( $opt_skip_ndbcluster )
+ {
+ mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
+ }
}
if ( $type eq 'slave' )
{
my $slave_server_id= 2 + $idx;
- my $slave_rpl_rank= $idx > 0 ? 2 : $slave_server_id;
+ my $slave_rpl_rank= $slave_server_id;
mtr_add_arg($args, "%s--datadir=%s", $prefix,
$slave->[$idx]->{'path_myddir'});
@@ -1803,6 +1761,7 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix);
mtr_add_arg($args, "%s--sort_buffer=256K", $prefix);
mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix);
+ mtr_add_arg($args, "%s--log-bin-trust-routine-creators", $prefix);
if ( $opt_with_openssl )
{
@@ -1850,7 +1809,7 @@ sub mysqld_arguments ($$$$$) {
}
}
- foreach my $arg ( @$extra_opt )
+ foreach my $arg ( @opt_extra_mysqld_opt, @$extra_opt )
{
mtr_add_arg($args, "%s%s", $prefix, $arg);
}
@@ -1860,19 +1819,11 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--rpl-recovery-rank=1", $prefix);
mtr_add_arg($args, "%s--init-rpl-role=master", $prefix);
}
- else
+ elsif ( $type eq 'master' )
{
mtr_add_arg($args, "%s--exit-info=256", $prefix);
mtr_add_arg($args, "%s--open-files-limit=1024", $prefix);
-
- if ( $type eq 'master' )
- {
- mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'});
- }
- if ( $type eq 'slave' )
- {
- mtr_add_arg($args, "%s--log=%s", $prefix, $slave->[0]->{'path_mylog'});
- }
+ mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'});
}
return $args;
@@ -2032,9 +1983,8 @@ sub stop_slaves () {
}
-sub run_mysqltest ($$) {
+sub run_mysqltest ($) {
my $tinfo= shift;
- my $master_opts= shift;
my $cmdline_mysqldump= "$exe_mysqldump --no-defaults -uroot " .
"--socket=$master->[0]->{'path_mysock'} --password=";
@@ -2044,8 +1994,16 @@ sub run_mysqltest ($$) {
" --debug=d:t:A,$opt_vardir/log/mysqldump.trace";
}
+ my $cmdline_mysqlshow= "$exe_mysqlshow -uroot " .
+ "--socket=$master->[0]->{'path_mysock'} --password=";
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlshow .=
+ " --debug=d:t:A,$opt_vardir/log/mysqlshow.trace";
+ }
+
my $cmdline_mysqlbinlog=
- "$exe_mysqlbinlog --no-defaults --local-load=$opt_tmpdir";
+ "$exe_mysqlbinlog --no-defaults --local-load=$opt_tmpdir --character-sets-dir=$path_charsetsdir";
if ( $opt_debug )
{
@@ -2063,6 +2021,14 @@ sub run_mysqltest ($$) {
"--port=$master->[0]->{'path_myport'} " .
"--socket=$master->[0]->{'path_mysock'}";
+ if ( $glob_use_embedded_server )
+ {
+ $cmdline_mysql_client_test.=
+ " -A --language=$path_language" .
+ " -A --datadir=$slave->[0]->{'path_myddir'}" .
+ " -A --character-sets-dir=$path_charsetsdir";
+ }
+
my $cmdline_mysql_fix_system_tables=
"$exe_mysql_fix_system_tables --no-defaults --host=localhost --user=root --password= " .
"--basedir=$glob_basedir --bindir=$path_client_bindir --verbose " .
@@ -2076,6 +2042,7 @@ sub run_mysqltest ($$) {
$ENV{'MYSQL'}= $cmdline_mysql;
$ENV{'MYSQL_DUMP'}= $cmdline_mysqldump;
+ $ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow;
$ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog;
$ENV{'MYSQL_FIX_SYSTEM_TABLES'}= $cmdline_mysql_fix_system_tables;
$ENV{'MYSQL_CLIENT_TEST'}= $cmdline_mysql_client_test;
@@ -2178,8 +2145,7 @@ sub run_mysqltest ($$) {
#
##############################################################################
-sub usage ($)
-{
+sub usage ($) {
print STDERR <<HERE;
mysql-test-run [ OPTIONS ] [ TESTCASE ]
@@ -2208,7 +2174,8 @@ Options that specify ports
master_port=PORT Specify the port number used by the first master
slave_port=PORT Specify the port number used by the first slave
- ndbcluster_port=i Specify the port number used by cluster FIXME
+ ndbcluster_port=PORT Specify the port number used by cluster
+ manager-port=PORT Specify the port number used by manager (currently not used)
Options for test case authoring
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index c5ddc28a996..081fec21563 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -170,7 +170,8 @@ cd ..
BASEDIR=`pwd`
cd $CWD
MYSQL_TEST_DIR=$BASEDIR/mysql-test
-export MYSQL_TEST_DIR
+MYSQL_TEST_WINDIR=$MYSQL_TEST_DIR
+export MYSQL_TEST_DIR MYSQL_TEST_WINDIR
STD_DATA=$MYSQL_TEST_DIR/std_data
hostname=`hostname` # Installed in the mysql privilege table
@@ -306,7 +307,7 @@ while test $# -gt 0; do
--ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \
--ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert.pem \
--ssl-key=$MYSQL_TEST_DIR/std_data/server-key.pem"
- MYSQL_TEST_SSL_OPTS="--ssl-ca=$BASEDIR/SSL/cacert.pem \
+ MYSQL_TEST_SSL_OPTS="--ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \
--ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem \
--ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem" ;;
--no-manager | --skip-manager) USE_MANAGER=0 ;;
@@ -706,6 +707,9 @@ MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --soc
if [ "x$USE_EMBEDDED_SERVER" = "x1" ]; then
MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST -A --language=$LANGUAGE -A --datadir=$SLAVE_MYDDIR -A --character-sets-dir=$CHARSETSDIR"
fi
+# Save path and name of mysqldump
+MYSQL_DUMP_DIR="$MYSQL_DUMP"
+export MYSQL_DUMP_DIR
MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSHOW_OPT"
MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT"
diff --git a/mysql-test/r/alias.result b/mysql-test/r/alias.result
index 587c21e9129..6f0315da234 100644
--- a/mysql-test/r/alias.result
+++ b/mysql-test/r/alias.result
@@ -27,7 +27,7 @@ hdl_name varchar(30) default NULL,
prov_hdl_nr int(11) NOT NULL default '0',
auto_wirknetz varchar(50) default NULL,
auto_billing varchar(50) default NULL,
-touch timestamp(14) NOT NULL,
+touch timestamp NOT NULL,
kategorie varchar(50) default NULL,
kundentyp varchar(20) NOT NULL default '',
sammel_rech_msisdn varchar(30) NOT NULL default '',
@@ -58,6 +58,8 @@ INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05
SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie;
Kundentyp kategorie
Privat (Private Nutzung) Mobilfunk
+Warnings:
+Warning 1052 Column 'kundentyp' in group statement is ambiguous
drop table t1;
CREATE TABLE t1 (
AUFNR varchar(12) NOT NULL default '',
diff --git a/mysql-test/r/bdb_cache.result b/mysql-test/r/bdb_cache.result
index 218fd489c6a..6506ce0412a 100644
--- a/mysql-test/r/bdb_cache.result
+++ b/mysql-test/r/bdb_cache.result
@@ -12,10 +12,9 @@ show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
-commit;
set autocommit=1;
-begin;
create table t1 (a int not null) engine=bdb;
+begin;
insert into t1 values (1),(2),(3);
select * from t1;
a
@@ -26,7 +25,6 @@ show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
-commit;
create table t1 (a int not null) engine=bdb;
create table t2 (a int not null) engine=bdb;
create table t3 (a int not null) engine=bdb;
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index a854cf4c7b0..b02f85132aa 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -160,6 +160,21 @@ t1 CREATE TABLE `t1` (
`COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
+SELECT 'case+union+test'
+UNION
+SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END;
+case+union+test
+case+union+test
+nobug
+SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END;
+CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END
+nobug
+SELECT 'case+union+test'
+UNION
+SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
+case+union+test
+case+union+test
+nobug
CREATE TABLE t1 (EMPNUM INT);
INSERT INTO t1 VALUES (0), (2);
CREATE TABLE t2 (EMPNUM DECIMAL (4, 2));
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 6dc608a9289..1b5bdf98afd 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -344,3 +344,14 @@ select cast(s1 as decimal(7,2)) from t1;
cast(s1 as decimal(7,2))
111111.00
drop table t1;
+CREATE TABLE t1 (v varchar(10), tt tinytext, t text,
+mt mediumtext, lt longtext);
+INSERT INTO t1 VALUES ('1.01', '2.02', '3.03', '4.04', '5.05');
+SELECT CAST(v AS DECIMAL), CAST(tt AS DECIMAL), CAST(t AS DECIMAL),
+CAST(mt AS DECIMAL), CAST(lt AS DECIMAL) from t1;
+CAST(v AS DECIMAL) CAST(tt AS DECIMAL) CAST(t AS DECIMAL) CAST(mt AS DECIMAL) CAST(lt AS DECIMAL)
+1.01 2.02 3.03 4.04 5.05
+DROP TABLE t1;
+select cast(NULL as decimal(6)) as t1;
+t1
+NULL
diff --git a/mysql-test/r/client_xml.result b/mysql-test/r/client_xml.result
index a4164148159..24c05c7f9d6 100644
--- a/mysql-test/r/client_xml.result
+++ b/mysql-test/r/client_xml.result
@@ -15,7 +15,7 @@ insert into t1 values (1, 2, 'a&b a<b a>b');
</row>
</resultset>
<?xml version="1.0"?>
-<mysqldump>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="test">
<table_structure name="t1">
<field Field="a&amp;b" Type="int(11)" Null="YES" Key="" Extra="" />
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 30f18c09dec..0407a7f388c 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -905,3 +905,37 @@ select * from t1 where city = 'Durban ';
id city
2 Durban
drop table t1;
+SET NAMES UTF8;
+CREATE TABLE t1 (
+`id` int(20) NOT NULL auto_increment,
+`country` varchar(100) NOT NULL default '',
+`shortcode` varchar(100) NOT NULL default '',
+`operator` varchar(100) NOT NULL default '',
+`momid` varchar(30) NOT NULL default '',
+`keyword` varchar(160) NOT NULL default '',
+`content` varchar(160) NOT NULL default '',
+`second_token` varchar(160) default NULL,
+`gateway_id` int(11) NOT NULL default '0',
+`created` datetime NOT NULL default '0000-00-00 00:00:00',
+`msisdn` varchar(15) NOT NULL default '',
+PRIMARY KEY (`id`),
+UNIQUE KEY `MSCCSPK_20030521130957121` (`momid`),
+KEY `IX_mobile_originated_message_keyword` (`keyword`),
+KEY `IX_mobile_originated_message_created` (`created`),
+KEY `IX_mobile_originated_message_support` (`msisdn`,`momid`,`keyword`,`gateway_id`,`created`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+INSERT INTO t1 VALUES
+(1,'blah','464','aaa','fkc1c9ilc20x0hgae7lx6j09','ERR','ERR Имри.Ðфимим.Ðеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ðд.Д имдимримрад.Ðдимримримрмдиримримримр м.Дадимфшьмримд им.Ðдимимрн имадми','ИМРИ.ÐФИМИМ.ÐЕИМИМРИМДМРИМРМРИРОР',3,'2005-06-01 17:30:43','1234567890'),
+(2,'blah','464','aaa','haxpl2ilc20x00bj4tt2m5ti','11','11 g','G',3,'2005-06-02 22:43:10','1234567890');
+CREATE TABLE t2 (
+`msisdn` varchar(15) NOT NULL default '',
+`operator_id` int(11) NOT NULL default '0',
+`created` datetime NOT NULL default '0000-00-00 00:00:00',
+UNIQUE KEY `PK_user` (`msisdn`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+INSERT INTO t2 VALUES ('1234567890',2,'2005-05-24 13:53:25');
+SELECT content, t2.msisdn FROM t1, t2 WHERE t1.msisdn = '1234567890';
+content msisdn
+ERR Имри.Ðфимим.Ðеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ðд.Д имдимримрад.Ðдимримримрмдиримримримр м.Дадимфшьмримд им.Ðдимимрн имадми 1234567890
+11 g 1234567890
+DROP TABLE t1,t2;
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index 34d1213d1b2..1a79f6d9736 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -339,7 +339,7 @@ insert into t2 values (3, 1, 'xxbuz');
select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode);
t1_id name t2_id t1_id name
1 data1 1 1 xxfoo
-select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode);
+select * from t2 where match name against ('*a*b*c*d*e*f*' in boolean mode);
t2_id t1_id name
drop table t1,t2;
create table t1 (a text, fulltext key (a));
diff --git a/mysql-test/r/func_date_add.result b/mysql-test/r/func_date_add.result
index f4091ff4c0e..50889943b56 100644
--- a/mysql-test/r/func_date_add.result
+++ b/mysql-test/r/func_date_add.result
@@ -4,7 +4,7 @@ visitor_id int(10) unsigned DEFAULT '0' NOT NULL,
group_id int(10) unsigned DEFAULT '0' NOT NULL,
hits int(10) unsigned DEFAULT '0' NOT NULL,
sessions int(10) unsigned DEFAULT '0' NOT NULL,
-ts timestamp(14),
+ts timestamp,
PRIMARY KEY (visitor_id,group_id)
)/*! engine=MyISAM */;
INSERT INTO t1 VALUES (465931136,7,2,2,20000318160952);
diff --git a/mysql-test/r/func_default.result b/mysql-test/r/func_default.result
index c7483027322..5742ddd102b 100644
--- a/mysql-test/r/func_default.result
+++ b/mysql-test/r/func_default.result
@@ -16,3 +16,8 @@ explain select * from t1 where str <> default(str);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
drop table t1;
+CREATE TABLE t1 (id int(11), s varchar(20));
+INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
+SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
+ERROR HY000: Field 'mi' doesn't have a default value
+DROP TABLE t1;
diff --git a/mysql-test/r/func_encrypt.result b/mysql-test/r/func_encrypt.result
index d32e67fe7d5..992d01c66cd 100644
--- a/mysql-test/r/func_encrypt.result
+++ b/mysql-test/r/func_encrypt.result
@@ -120,6 +120,60 @@ hello
select des_decrypt(des_encrypt("hello",4),'password4');
des_decrypt(des_encrypt("hello",4),'password4')
hello
+select des_encrypt("hello",10);
+des_encrypt("hello",10)
+NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_encrypt'
+select des_encrypt(NULL);
+des_encrypt(NULL)
+NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_encrypt'
+select des_encrypt(NULL, 10);
+des_encrypt(NULL, 10)
+NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_encrypt'
+select des_encrypt(NULL, NULL);
+des_encrypt(NULL, NULL)
+NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_encrypt'
+select des_encrypt(10, NULL);
+des_encrypt(10, NULL)
+NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_encrypt'
+select des_encrypt("hello", NULL);
+des_encrypt("hello", NULL)
+NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_encrypt'
+select des_decrypt("hello",10);
+des_decrypt("hello",10)
+hello
+select des_decrypt(NULL);
+des_decrypt(NULL)
+NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_decrypt'
+select des_decrypt(NULL, 10);
+des_decrypt(NULL, 10)
+NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_decrypt'
+select des_decrypt(NULL, NULL);
+des_decrypt(NULL, NULL)
+NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_decrypt'
+select des_decrypt(10, NULL);
+des_decrypt(10, NULL)
+10
+select des_decrypt("hello", NULL);
+des_decrypt("hello", NULL)
+hello
SET @a=des_decrypt(des_encrypt("hello"));
flush des_key_file;
select @a = des_decrypt(des_encrypt("hello"));
@@ -134,6 +188,8 @@ NULL
select hex(des_decrypt(des_encrypt("hello","hidden")));
hex(des_decrypt(des_encrypt("hello","hidden")))
NULL
+Warnings:
+Error 1108 Incorrect parameters to procedure 'des_decrypt'
explain extended select des_decrypt(des_encrypt("hello",4),'password2'), des_decrypt(des_encrypt("hello","hidden"));
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
diff --git a/mysql-test/r/func_encrypt_nossl.result b/mysql-test/r/func_encrypt_nossl.result
new file mode 100644
index 00000000000..fea752f4a4a
--- /dev/null
+++ b/mysql-test/r/func_encrypt_nossl.result
@@ -0,0 +1,93 @@
+select des_encrypt("test", 'akeystr');
+des_encrypt("test", 'akeystr')
+NULL
+Warnings:
+Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_encrypt("test", 1);
+des_encrypt("test", 1)
+NULL
+Warnings:
+Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_encrypt("test", 9);
+des_encrypt("test", 9)
+NULL
+Warnings:
+Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_encrypt("test", 100);
+des_encrypt("test", 100)
+NULL
+Warnings:
+Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_encrypt("test", NULL);
+des_encrypt("test", NULL)
+NULL
+Warnings:
+Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_decrypt("test", 'anotherkeystr');
+des_decrypt("test", 'anotherkeystr')
+NULL
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_decrypt(1, 1);
+des_decrypt(1, 1)
+NULL
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_decrypt(des_encrypt("test", 'thekey'));
+des_decrypt(des_encrypt("test", 'thekey'))
+NULL
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello"));
+hex(des_encrypt("hello")) des_decrypt(des_encrypt("hello"))
+NULL NULL
+Warnings:
+Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_decrypt(des_encrypt("hello",4));
+des_decrypt(des_encrypt("hello",4))
+NULL
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_decrypt(des_encrypt("hello",'test'),'test');
+des_decrypt(des_encrypt("hello",'test'),'test')
+NULL
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password'));
+hex(des_encrypt("hello")) hex(des_encrypt("hello",5)) hex(des_encrypt("hello",'default_password'))
+NULL NULL NULL
+Warnings:
+Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_decrypt(des_encrypt("hello"),'default_password');
+des_decrypt(des_encrypt("hello"),'default_password')
+NULL
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select des_decrypt(des_encrypt("hello",4),'password4');
+des_decrypt(des_encrypt("hello",4),'password4')
+NULL
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+SET @a=des_decrypt(des_encrypt("hello"));
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+flush des_key_file;
+select @a = des_decrypt(des_encrypt("hello"));
+@a = des_decrypt(des_encrypt("hello"))
+NULL
+select hex("hello");
+hex("hello")
+68656C6C6F
+select hex(des_decrypt(des_encrypt("hello",4),'password2'));
+hex(des_decrypt(des_encrypt("hello",4),'password2'))
+NULL
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+select hex(des_decrypt(des_encrypt("hello","hidden")));
+hex(des_decrypt(des_encrypt("hello","hidden")))
+NULL
+Warnings:
+Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result
index 3e72fb45a14..aee23b38ca5 100644
--- a/mysql-test/r/func_if.result
+++ b/mysql-test/r/func_if.result
@@ -108,3 +108,16 @@ id date_ord text
2 16-03-2005 Day 2
1 05-03-2005 Day 1
DROP TABLE t1;
+CREATE TABLE t1 (a CHAR(10));
+INSERT INTO t1 VALUES ('aaa'), (NULL), (''), ('bbb');
+SELECT a, NULLIF(a,'') FROM t1;
+a NULLIF(a,'')
+aaa aaa
+NULL NULL
+ NULL
+bbb bbb
+SELECT a, NULLIF(a,'') FROM t1 WHERE NULLIF(a,'') IS NULL;
+a NULLIF(a,'')
+NULL NULL
+ NULL
+DROP TABLE t1;
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index c7674c57c8d..b7188092b41 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -146,3 +146,9 @@ drop table t1;
select round(150, 2);
round(150, 2)
150.00
+select ceil(0.09);
+ceil(0.09)
+1
+select ceil(0.000000000000000009);
+ceil(0.000000000000000009)
+1
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 1c6a4393dfc..3ae2adaf5e7 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -264,7 +264,7 @@ category int(10) unsigned default NULL,
program int(10) unsigned default NULL,
bugdesc text,
created datetime default NULL,
-modified timestamp(14) NOT NULL,
+modified timestamp NOT NULL,
bugstatus int(10) unsigned default NULL,
submitter int(10) unsigned default NULL
) ENGINE=MyISAM;
@@ -800,3 +800,14 @@ field(0,NULL,1,0) field("",NULL,"bar","") field(0.0,NULL,1.0,0.0)
select field(NULL,1,2,NULL), field(NULL,1,2,0);
field(NULL,1,2,NULL) field(NULL,1,2,0)
0 0
+CREATE TABLE t1 (str varchar(20) PRIMARY KEY);
+CREATE TABLE t2 (num int primary key);
+INSERT INTO t1 VALUES ('notnumber');
+INSERT INTO t2 VALUES (0), (1);
+SELECT * FROM t1, t2 WHERE num=str;
+str num
+notnumber 0
+SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6);
+str num
+notnumber 0
+DROP TABLE t1,t2;
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index cb51da75368..63da5589c57 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -465,7 +465,7 @@ extract(MONTH FROM "0000-00-00") extract(MONTH FROM d) extract(MONTH FROM dt) ex
drop table t1;
CREATE TABLE t1 ( start datetime default NULL);
INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00');
-CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL);
+CREATE TABLE t2 ( ctime1 timestamp NOT NULL, ctime2 timestamp NOT NULL);
INSERT INTO t2 VALUES (20021029165106,20021105164731);
CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 937ed401f40..a56cfd4492a 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -117,7 +117,7 @@ bug_file_loc text,
bug_severity enum('blocker','critical','major','normal','minor','trivial','enhancement') DEFAULT 'blocker' NOT NULL,
bug_status enum('','NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','CLOSED') DEFAULT 'NEW' NOT NULL,
creation_ts datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
-delta_ts timestamp(14),
+delta_ts timestamp,
short_desc mediumtext,
long_desc mediumtext,
op_sys enum('All','Windows 3.1','Windows 95','Windows 98','Windows NT','Windows 2000','Linux','other') DEFAULT 'All' NOT NULL,
@@ -722,3 +722,32 @@ WHERE hostname LIKE '%aol%'
GROUP BY hostname;
hostname no
cache-dtc-af05.proxy.aol.com 1
+DROP TABLE t1;
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,2), (1,3);
+SELECT a, b FROM t1 GROUP BY 'const';
+a b
+1 2
+SELECT DISTINCT a, b FROM t1 GROUP BY 'const';
+a b
+1 2
+DROP TABLE t1;
+CREATE TABLE t1 (id INT, dt DATETIME);
+INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
+INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
+INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
+INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
+SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f;
+f id
+20050501123000 1
+DROP TABLE t1;
+CREATE TABLE t1 (id varchar(20) NOT NULL);
+INSERT INTO t1 VALUES ('trans1'), ('trans2');
+CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL);
+INSERT INTO t2 VALUES ('trans1', 'a problem');
+SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment
+FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY comment;
+COUNT(DISTINCT(t1.id)) comment
+1 NULL
+1 a problem
+DROP TABLE t1, t2;
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index a43f1ee88a6..13eb2690e86 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -1954,6 +1954,24 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 128 Using where; Using index
+explain select a1 from t1 where a2 = 'b' group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using where; Using index for group-by
+select a1 from t1 where a2 = 'b' group by a1;
+a1
+a
+b
+c
+d
+explain select distinct a1 from t1 where a2 = 'b';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using where; Using index for group-by
+select distinct a1 from t1 where a2 = 'b';
+a1
+a
+b
+c
+d
drop table t1;
drop table t2;
drop table t3;
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 86c9adf8cf6..35a1358dd0c 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -304,6 +304,7 @@ s1
0
0
Warnings:
+Warning 1052 Column 's1' in group statement is ambiguous
Warning 1052 Column 's1' in having clause is ambiguous
select s1*0 from t1 group by s1 having s1 = 0;
s1*0
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index 22304c4a93d..b905dae3aba 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -367,13 +367,13 @@ count(*)
9
explain select count(*) from t1 where v='a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref v v 13 const 9 Using where
+1 SIMPLE t1 ref v v 13 const 10 Using where
explain select count(*) from t1 where c='a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref c c 11 const 9 Using where
+1 SIMPLE t1 ref c c 11 const 10 Using where
explain select count(*) from t1 where t='a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref t t 13 const 9 Using where
+1 SIMPLE t1 ref t t 13 const 10 Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
@@ -399,7 +399,7 @@ qq
*a *a*a *
explain select * from t1 where v='a';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref v v 13 const 9 Using where
+1 SIMPLE t1 ref v v 13 const 10 Using where
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result
index 9720fe4843a..d8d89b786b5 100644
--- a/mysql-test/r/heap_hash.result
+++ b/mysql-test/r/heap_hash.result
@@ -231,18 +231,19 @@ explain select * from t1 where a='aaad';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a a 8 const 1 Using where
insert into t1 select * from t1;
+flush tables;
explain select * from t1 where a='aaaa';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 8 const 1 Using where
+1 SIMPLE t1 ref a a 8 const 2 Using where
explain select * from t1 where a='aaab';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 8 const 1 Using where
+1 SIMPLE t1 ref a a 8 const 2 Using where
explain select * from t1 where a='aaac';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 8 const 1 Using where
+1 SIMPLE t1 ref a a 8 const 2 Using where
explain select * from t1 where a='aaad';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 8 const 1 Using where
+1 SIMPLE t1 ref a a 8 const 2 Using where
flush tables;
explain select * from t1 where a='aaaa';
id select_type table type possible_keys key key_len ref rows Extra
@@ -261,16 +262,16 @@ delete from t1;
insert into t1 select * from t2;
explain select * from t1 where a='aaaa';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 8 const 1 Using where
+1 SIMPLE t1 ref a a 8 const 2 Using where
explain select * from t1 where a='aaab';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 8 const 1 Using where
+1 SIMPLE t1 ref a a 8 const 2 Using where
explain select * from t1 where a='aaac';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 8 const 1 Using where
+1 SIMPLE t1 ref a a 8 const 2 Using where
explain select * from t1 where a='aaad';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 8 const 1 Using where
+1 SIMPLE t1 ref a a 8 const 2 Using where
drop table t1, t2;
create table t1 (
id int unsigned not null primary key auto_increment,
@@ -345,15 +346,15 @@ insert into t3 select name, name from t1;
show index from t3;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t3 1 a 1 a NULL NULL NULL NULL HASH
-t3 1 a 2 b NULL 15 NULL NULL HASH
+t3 1 a 2 b NULL 13 NULL NULL HASH
show index from t3;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t3 1 a 1 a NULL NULL NULL NULL HASH
-t3 1 a 2 b NULL 15 NULL NULL HASH
+t3 1 a 2 b NULL 13 NULL NULL HASH
explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 ref a a 44 const,const 6 Using where
1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where
+1 SIMPLE t3 ref a a 44 const,const 7 Using where
drop table t1, t2, t3;
create temporary table t1 ( a int, index (a) ) engine=memory;
insert into t1 values (1),(2),(3),(4),(5);
diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result
index 8f5db550d8b..d039d5a04c9 100644
--- a/mysql-test/r/index_merge.result
+++ b/mysql-test/r/index_merge.result
@@ -371,8 +371,8 @@ alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(20
update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500;
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
-where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key# = 1 or A.key8=1)
-and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key# = 1 or B.key8=1);
+where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
+and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL # Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where
1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL # Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where
diff --git a/mysql-test/r/index_merge_innodb.result b/mysql-test/r/index_merge_innodb.result
index 52e2a4046cf..662fffe1ba1 100644
--- a/mysql-test/r/index_merge_innodb.result
+++ b/mysql-test/r/index_merge_innodb.result
@@ -123,3 +123,14 @@ key1a = 2 and key1b is null and key3a = 2 and key3b is null;
count(*)
4
drop table t1,t2;
+create table t1 (
+id1 int,
+id2 date ,
+index idx2 (id1,id2),
+index idx1 (id2)
+) engine = innodb;
+insert into t1 values(1,'20040101'), (2,'20040102');
+select * from t1 where id1 = 1 and id2= '20040101';
+id1 id2
+1 2004-01-01
+drop table t1;
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index 38eb1d6a3ae..c6090bc663d 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -823,3 +823,15 @@ GRANT SELECT ON *.* TO 'user4'@'localhost'
drop user user1@localhost, user2@localhost, user3@localhost, user4@localhost;
use test;
drop database mysqltest;
+create procedure p1 () modifies sql data set @a = 5;
+create procedure p2 () set @a = 5;
+select sql_data_access from information_schema.routines
+where specific_name like 'p%';
+sql_data_access
+MODIFIES SQL DATA
+CONTAINS SQL
+drop procedure p1;
+drop procedure p2;
+show create database information_schema;
+Database Create Database
+information_schema CREATE DATABASE `information_schema` /*!40100 DEFAULT CHARACTER SET utf8 */
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 31480e32c16..aab4eb696d2 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -909,7 +909,6 @@ set autocommit=0;
create table t1 (a int not null) engine= innodb;
insert into t1 values(1),(2);
truncate table t1;
-ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
commit;
truncate table t1;
truncate table t1;
@@ -973,9 +972,9 @@ number bigint(20) NOT NULL default '0',
cname char(15) NOT NULL default '',
carrier_id smallint(6) NOT NULL default '0',
privacy tinyint(4) NOT NULL default '0',
-last_mod_date timestamp(14) NOT NULL,
+last_mod_date timestamp NOT NULL,
last_mod_id smallint(6) NOT NULL default '0',
-last_app_date timestamp(14) NOT NULL,
+last_app_date timestamp NOT NULL,
last_app_id smallint(6) default '-1',
version smallint(6) NOT NULL default '0',
assigned_scps int(11) default '0',
@@ -992,9 +991,9 @@ number bigint(20) NOT NULL default '0',
cname char(15) NOT NULL default '',
carrier_id smallint(6) NOT NULL default '0',
privacy tinyint(4) NOT NULL default '0',
-last_mod_date timestamp(14) NOT NULL,
+last_mod_date timestamp NOT NULL,
last_mod_id smallint(6) NOT NULL default '0',
-last_app_date timestamp(14) NOT NULL,
+last_app_date timestamp NOT NULL,
last_app_id smallint(6) default '-1',
version smallint(6) NOT NULL default '0',
assigned_scps int(11) default '0',
@@ -1638,14 +1637,14 @@ t2 CREATE TABLE `t2` (
drop table t2, t1;
show status like "binlog_cache_use";
Variable_name Value
-Binlog_cache_use 153
+Binlog_cache_use 155
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
-Binlog_cache_use 154
+Binlog_cache_use 156
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
@@ -1654,7 +1653,7 @@ delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
-Binlog_cache_use 155
+Binlog_cache_use 157
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
@@ -1722,12 +1721,13 @@ count(*)
0
explain select count(*) from t1 where x > -16;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL 1 Using where; Using index
+1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 2 Using where; Using index
select count(*) from t1 where x > -16;
count(*)
-1
+2
select * from t1 where x > -16;
x
+18446744073709551600
18446744073709551601
select count(*) from t1 where x = 18446744073709551601;
count(*)
@@ -1780,7 +1780,7 @@ Variable_name Value
innodb_sync_spin_loops 20
show variables like "innodb_thread_concurrency";
Variable_name Value
-innodb_thread_concurrency 8
+innodb_thread_concurrency 20
set global innodb_thread_concurrency=1000;
show variables like "innodb_thread_concurrency";
Variable_name Value
diff --git a/mysql-test/r/innodb_cache.result b/mysql-test/r/innodb_cache.result
index ec43cbe10b2..5e8611655a2 100644
--- a/mysql-test/r/innodb_cache.result
+++ b/mysql-test/r/innodb_cache.result
@@ -24,7 +24,7 @@ a
3
show status like "Qcache_queries_in_cache";
Variable_name Value
-Qcache_queries_in_cache 0
+Qcache_queries_in_cache 1
drop table t1;
commit;
create table t1 (a int not null) engine=innodb;
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index d2c0a665845..026dae8381a 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -625,3 +625,27 @@ select SQL_BUFFER_RESULT * from t1 WHERE (SEQ = 1);
ID NO SEQ
1 1 1
drop table t1;
+create table t1 (f1 int);
+create table t2 (ff1 int unique, ff2 int default 1);
+insert into t1 values (1),(1),(2);
+insert into t2(ff1) select f1 from t1 on duplicate key update ff2=ff2+1;
+select * from t2;
+ff1 ff2
+1 2
+2 1
+drop table t1, t2;
+create table t1 (a int unique);
+create table t2 (a int, b int);
+insert into t1 values (1),(2);
+insert into t2 values (1,2);
+select * from t1;
+a
+1
+2
+insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b;
+select * from t1;
+a
+2
+3
+drop table t1;
+drop table t2;
diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result
index 6d3aa941c8c..739beea6286 100644
--- a/mysql-test/r/insert_update.result
+++ b/mysql-test/r/insert_update.result
@@ -1,4 +1,4 @@
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
INSERT t1 VALUES (1,2,10), (3,4,20);
INSERT t1 VALUES (5,6,30) ON DUPLICATE KEY UPDATE c=c+100;
diff --git a/mysql-test/r/join_nested.result b/mysql-test/r/join_nested.result
index bce086b00d2..27edac1b30b 100644
--- a/mysql-test/r/join_nested.result
+++ b/mysql-test/r/join_nested.result
@@ -1321,3 +1321,25 @@ NULL NULL NULL
18 NULL NULL
19 NULL NULL
DROP TABLE t1,t2,t3;
+CREATE TABLE t1 (c11 int);
+CREATE TABLE t2 (c21 int);
+CREATE TABLE t3 (c31 int);
+INSERT INTO t1 VALUES (4), (5);
+SELECT * FROM t1 LEFT JOIN t2 ON c11=c21;
+c11 c21
+4 NULL
+5 NULL
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON c11=c21;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 system NULL NULL NULL NULL 0 const row not found
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON c21=c31) ON c11=c21;
+c11 c21 c31
+4 NULL NULL
+5 NULL NULL
+EXPLAIN SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON c21=c31) ON c11=c21;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL NULL NULL NULL NULL 0
+1 SIMPLE t3 ALL NULL NULL NULL NULL 0
+DROP TABLE t1,t2,t3;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index e69e7603e21..b75eadd5291 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -975,3 +975,11 @@ EMPNUM NAME GRP
0 KERI 10
9 BARRY NULL
DROP TABLE t1,t2;
+CREATE TABLE t1 (c11 int);
+CREATE TABLE t2 (c21 int);
+INSERT INTO t1 VALUES (30), (40), (50);
+INSERT INTO t2 VALUES (300), (400), (500);
+SELECT * FROM t1 LEFT JOIN t2 ON (c11=c21 AND c21=30) WHERE c11=40;
+c11 c21
+40 NULL
+DROP TABLE t1, t2;
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result
index 9eedbf50064..73e3a9d32e3 100644
--- a/mysql-test/r/lock_multi.result
+++ b/mysql-test/r/lock_multi.result
@@ -36,3 +36,10 @@ lock table t1 write, t2 write;
drop table t2;
ERROR 42S02: Table 'test.t2' doesn't exist
drop table t1;
+create table t1(a int);
+lock tables t1 write;
+show columns from t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+unlock tables;
+drop table t1;
diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result
index feb0b2348cd..dbb47152926 100644
--- a/mysql-test/r/mysql.result
+++ b/mysql-test/r/mysql.result
@@ -48,3 +48,9 @@ Test 'go' command g
a
1
drop table t1;
+create table t1(a int);
+lock tables t1 write;
+database()
+test
+unlock tables;
+drop table t1;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index f73c9b223fd..573b2b54141 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -1,10 +1,11 @@
DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa;
drop database if exists mysqldump_test_db;
-drop view if exists v1;
+drop database if exists db1;
+drop view if exists v1, v2;
CREATE TABLE t1(a int);
INSERT INTO t1 VALUES (1), (2);
<?xml version="1.0"?>
-<mysqldump>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="test">
<table_structure name="t1">
<field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
@@ -107,7 +108,7 @@ DROP TABLE t1;
CREATE TABLE t1(a int, b text, c varchar(3));
INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES");
<?xml version="1.0"?>
-<mysqldump>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="test">
<table_structure name="t1">
<field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
@@ -132,7 +133,7 @@ DROP TABLE t1;
CREATE TABLE t1 (`a"b"` char(2));
INSERT INTO t1 VALUES ("1\""), ("\"2");
<?xml version="1.0"?>
-<mysqldump>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="test">
<table_structure name="t1">
<field Field="a&quot;b&quot;" Type="char(2)" Null="YES" Key="" Extra="" />
@@ -1422,3 +1423,217 @@ UNLOCK TABLES;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
DROP TABLE t1;
+create database db1;
+use db1;
+CREATE TABLE t2 (
+a varchar(30) default NULL,
+KEY a (a(5))
+);
+INSERT INTO t2 VALUES ('alfred');
+INSERT INTO t2 VALUES ('angie');
+INSERT INTO t2 VALUES ('bingo');
+INSERT INTO t2 VALUES ('waffle');
+INSERT INTO t2 VALUES ('lemon');
+create view v2 as select * from t2 where a like 'a%' with check option;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES 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' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t2`;
+CREATE TABLE `t2` (
+ `a` varchar(30) default NULL,
+ KEY `a` (`a`(5))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
+LOCK TABLES `t2` WRITE;
+INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon');
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
+DROP TABLE IF EXISTS `v2`;
+DROP VIEW IF EXISTS `v2`;
+CREATE ALGORITHM=UNDEFINED VIEW `db1`.`v2` AS select `db1`.`t2`.`a` AS `a` from `db1`.`t2` where (`db1`.`t2`.`a` like _latin1'a%') WITH CASCADED CHECK OPTION;
+
+/*!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 */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+drop table t2;
+drop view v2;
+drop database db1;
+CREATE DATABASE mysqldump_test_db;
+USE mysqldump_test_db;
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+INSERT INTO t1 VALUES (1), (2);
+INSERT INTO t2 VALUES (1), (2);
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES 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' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS `t2`;
+CREATE TABLE `t2` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+/*!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 */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES 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' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS `t2`;
+CREATE TABLE `t2` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+/*!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 */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="mysqldump_test_db">
+ <table_structure name="t1">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ </table_structure>
+ <table_structure name="t2">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ </table_structure>
+</database>
+</mysqldump>
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="mysqldump_test_db">
+ <table_structure name="t1">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ </table_structure>
+ <table_structure name="t2">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ </table_structure>
+</database>
+</mysqldump>
+DROP TABLE t1, t2;
+DROP DATABASE mysqldump_test_db;
+create database mysqldump_test_db;
+use mysqldump_test_db;
+create table t1(a varchar(30) primary key, b int not null);
+create table t2(a varchar(30) primary key, b int not null);
+create table t3(a varchar(30) primary key, b int not null);
+test_sequence
+------ Testing with illegal table names ------
+mysqldump: Couldn't find table: "\d-2-1.sql"
+
+mysqldump: Couldn't find table: "\t1"
+
+mysqldump: Couldn't find table: "\t1"
+
+mysqldump: Couldn't find table: "\\t1"
+
+mysqldump: Couldn't find table: "t\1"
+
+mysqldump: Couldn't find table: "t\1"
+
+mysqldump: Couldn't find table: "t/1"
+
+test_sequence
+------ Testing with illegal database names ------
+mysqldump: Got error: 1049: Unknown database 'mysqldump_test_d' when selecting the database
+mysqldump: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when selecting the database
+drop table t1, t2, t3;
+drop database mysqldump_test_db;
+use test;
+create table t1 (a int(10));
+create table t2 (pk int primary key auto_increment,
+a int(10), b varchar(30), c datetime, d blob, e text);
+insert into t1 values (NULL), (10), (20);
+insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thirty");
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="test">
+ <table_data name="t1">
+ <row>
+ <field name="a" xsi:nil="true" />
+ </row>
+ <row>
+ <field name="a">10</field>
+ </row>
+ <row>
+ <field name="a">20</field>
+ </row>
+ </table_data>
+ <table_data name="t2">
+ <row>
+ <field name="pk">1</field>
+ <field name="a" xsi:nil="true" />
+ <field name="b" xsi:nil="true" />
+ <field name="c" xsi:nil="true" />
+ <field name="d" xsi:nil="true" />
+ <field name="e" xsi:nil="true" />
+ </row>
+ <row>
+ <field name="pk">2</field>
+ <field name="a">10</field>
+ <field name="b" xsi:nil="true" />
+ <field name="c" xsi:nil="true" />
+ <field name="d" xsi:nil="true" />
+ <field name="e" xsi:nil="true" />
+ </row>
+ <row>
+ <field name="pk">3</field>
+ <field name="a" xsi:nil="true" />
+ <field name="b">twenty</field>
+ <field name="c" xsi:nil="true" />
+ <field name="d" xsi:nil="true" />
+ <field name="e" xsi:nil="true" />
+ </row>
+ <row>
+ <field name="pk">4</field>
+ <field name="a">30</field>
+ <field name="b">thirty</field>
+ <field name="c" xsi:nil="true" />
+ <field name="d" xsi:nil="true" />
+ <field name="e" xsi:nil="true" />
+ </row>
+ </table_data>
+</database>
+</mysqldump>
+drop table t1, t2;
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index 87e2fca970b..2b171229096 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -148,17 +148,19 @@ a'b a"b
select 'aaa\\','aa''a',"aa""a";
aaa\ aa'a aa"a
aaa\ aa'a aa"a
-SET @message = 'Here comes a message';
Here comes a message
--------------------
-SET @message = USER();
root@localhost
--------------
-SET @message = 'Here comes a very very long message that is longer then 80 characters
-on multiple lines';
-Here comes a very very long message that is longer then 80 characters
-on multiple lines
+"Here comes a very very long message that
+ - is longer then 80 characters and
+ - consists of several lines"
+--------------------------------------------------------------------------------
+
+. Here comes a very very long message that
+. - is longer then 80 characters and
+. - consists of several lines
--------------------------------------------------------------------------------
diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result
index 27ebda36669..babe3d0fe41 100644
--- a/mysql-test/r/ndb_autodiscover.result
+++ b/mysql-test/r/ndb_autodiscover.result
@@ -93,7 +93,7 @@ name char(20), a int, b float, c char(24)
ERROR 42S01: Table 't3' already exists
show status like 'handler_discover%';
Variable_name Value
-Handler_discover 1
+Handler_discover 0
create table IF NOT EXISTS t3(
id int not null primary key,
id2 int not null,
@@ -101,7 +101,7 @@ name char(20)
) engine=ndb;
show status like 'handler_discover%';
Variable_name Value
-Handler_discover 2
+Handler_discover 0
SHOW CREATE TABLE t3;
Table Create Table
t3 CREATE TABLE `t3` (
@@ -114,7 +114,7 @@ id name
1 Explorer
show status like 'handler_discover%';
Variable_name Value
-Handler_discover 2
+Handler_discover 1
drop table t3;
flush status;
create table t7(
@@ -383,6 +383,20 @@ select * from t1;
ERROR HY000: Can't lock file (errno: 4009)
use test;
drop database test_only_ndb_tables;
+CREATE TABLE sys.SYSTAB_0 (a int);
+ERROR 42S01: Table 'SYSTAB_0' already exists
+select * from sys.SYSTAB_0;
+ERROR HY000: Failed to open 'SYSTAB_0', error while unpacking from engine
+CREATE TABLE IF NOT EXISTS sys.SYSTAB_0 (a int);
+show warnings;
+Level Code Message
+select * from sys.SYSTAB_0;
+ERROR HY000: Failed to open 'SYSTAB_0', error while unpacking from engine
+drop table sys.SYSTAB_0;
+ERROR 42S02: Unknown table 'SYSTAB_0'
+drop table IF EXISTS sys.SYSTAB_0;
+Warnings:
+Note 1051 Unknown table 'SYSTAB_0'
CREATE TABLE t9 (
a int NOT NULL PRIMARY KEY,
b int
diff --git a/mysql-test/r/ndb_insert.result b/mysql-test/r/ndb_insert.result
index 7503010a66b..464eeb6d607 100644
--- a/mysql-test/r/ndb_insert.result
+++ b/mysql-test/r/ndb_insert.result
@@ -416,10 +416,12 @@ INSERT INTO t1 VALUES
SELECT COUNT(*) FROM t1;
COUNT(*)
2000
+INSERT INTO t1 VALUES (1,1,1);
+ERROR 23000: Duplicate entry '1' for key 1
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
-ERROR 23000: Duplicate entry '10' for key 1
+ERROR 23000: Can't write; duplicate key in table 't1'
select count(*) from t1;
count(*)
2000
@@ -437,7 +439,7 @@ begin;
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
-ERROR 23000: Duplicate entry '10' for key 1
+ERROR 23000: Can't write; duplicate key in table 't1'
commit;
ERROR HY000: Got error 4350 'Transaction already aborted' from ndbcluster
select * from t1 where pk1=1;
@@ -456,7 +458,7 @@ begin;
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
-ERROR 23000: Duplicate entry '10' for key 1
+ERROR 23000: Can't write; duplicate key in table 't1'
rollback;
select * from t1 where pk1=1;
pk1 b c
@@ -474,7 +476,7 @@ begin;
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
-ERROR 23000: Duplicate entry '10' for key 1
+ERROR 23000: Can't write; duplicate key in table 't1'
SELECT * FROM t1 WHERE pk1=10;
ERROR HY000: Got error 4350 'Transaction already aborted' from ndbcluster
rollback;
@@ -494,7 +496,7 @@ begin;
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
-ERROR 23000: Duplicate entry '10' for key 1
+ERROR 23000: Can't write; duplicate key in table 't1'
SELECT * FROM t1 WHERE pk1=10;
ERROR HY000: Got error 4350 'Transaction already aborted' from ndbcluster
SELECT * FROM t1 WHERE pk1=10;
@@ -517,7 +519,7 @@ begin;
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
-ERROR 23000: Duplicate entry '10' for key 1
+ERROR 23000: Can't write; duplicate key in table 't1'
INSERT INTO t1 values (4000, 40, 44);
ERROR HY000: Got error 4350 'Transaction already aborted' from ndbcluster
rollback;
@@ -534,7 +536,7 @@ select count(*) from t1;
count(*)
2000
insert into t1 select * from t1 where b < 10 order by pk1;
-ERROR 23000: Duplicate entry '9' for key 1
+ERROR 23000: Can't write; duplicate key in table 't1'
DELETE FROM t1 WHERE pk1=2;
begin;
INSERT IGNORE INTO t1 VALUES(1,2,3),(2,3,4);
diff --git a/mysql-test/r/not_openssl.require b/mysql-test/r/not_openssl.require
new file mode 100644
index 00000000000..2b5e423999c
--- /dev/null
+++ b/mysql-test/r/not_openssl.require
@@ -0,0 +1,2 @@
+Variable_name Value
+have_openssl NO
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 496d566a5ee..bd06be07a8e 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -138,7 +138,7 @@ create table t1
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 bit, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -675,3 +675,9 @@ a
10
drop table t1;
deallocate prepare stmt;
+create table t1 (id int);
+prepare stmt from "insert into t1 (id) select id from t1 union select id from t1";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+drop table t1;
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index 54c35873201..75824aa7213 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -17,7 +17,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 3df9b6dcb6e..a9342636349 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -10,7 +10,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -444,7 +444,7 @@ limit 1 ';
execute stmt1 ;
a b
1 one
-prepare stmt1 from ' select a,b from t1 limit ? ';
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
execute stmt1 using @arg00;
a b
1 one
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 851178e2aee..3a470d218d1 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -10,7 +10,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -444,7 +444,7 @@ limit 1 ';
execute stmt1 ;
a b
1 one
-prepare stmt1 from ' select a,b from t1 limit ? ';
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
execute stmt1 using @arg00;
a b
1 one
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index 60675a72bdc..beeaff05ece 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -11,7 +11,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100),
c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100),
@@ -445,7 +445,7 @@ limit 1 ';
execute stmt1 ;
a b
1 one
-prepare stmt1 from ' select a,b from t1 limit ? ';
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
execute stmt1 using @arg00;
a b
1 one
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index a177290daa4..fada983a561 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -12,7 +12,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -32,7 +32,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -52,7 +52,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -487,7 +487,7 @@ limit 1 ';
execute stmt1 ;
a b
1 one
-prepare stmt1 from ' select a,b from t1 limit ? ';
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
execute stmt1 using @arg00;
a b
1 one
@@ -3064,7 +3064,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -3499,7 +3499,7 @@ limit 1 ';
execute stmt1 ;
a b
1 one
-prepare stmt1 from ' select a,b from t1 limit ? ';
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
execute stmt1 using @arg00;
a b
1 one
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
index 92399c3b3b9..404c25c2c37 100644
--- a/mysql-test/r/ps_6bdb.result
+++ b/mysql-test/r/ps_6bdb.result
@@ -10,7 +10,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -444,7 +444,7 @@ limit 1 ';
execute stmt1 ;
a b
1 one
-prepare stmt1 from ' select a,b from t1 limit ? ';
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
execute stmt1 using @arg00;
a b
1 one
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index c7dabc2016d..ffddec6d5c2 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -10,7 +10,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -444,10 +444,10 @@ limit 1 ';
execute stmt1 ;
a b
1 one
-prepare stmt1 from ' select a,b from t1 limit ? ';
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
execute stmt1 using @arg00;
a b
-3 three
+1 one
set @arg00='b' ;
set @arg01=0 ;
set @arg02=2 ;
diff --git a/mysql-test/r/ps_grant.result b/mysql-test/r/ps_grant.result
index 8fbb06fe61b..651ac171e5d 100644
--- a/mysql-test/r/ps_grant.result
+++ b/mysql-test/r/ps_grant.result
@@ -90,5 +90,5 @@ drop user drop_user@localhost;
prepare stmt4 from ' show full processlist ';
execute stmt4;
Id User Host db Command Time State Info
-number root localhost test Query time NULL show full processlist
+number root localhost test Execute time NULL show full processlist
deallocate prepare stmt4;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 385ac1f4dfb..506a76579ae 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -1007,4 +1007,33 @@ abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba
flush query cache;
drop table t1, t2;
+create table t1 (a int);
+insert into t1 values (1),(2);
+CREATE PROCEDURE `p1`()
+begin
+Declare c1 cursor for select a from t1;
+open c1;
+select * from t1;
+end//
+call p1()//
+a
+1
+2
+drop procedure p1;
+create function f1() returns int
+begin
+Declare var1 int;
+select max(a) from t1 into var1;
+return var1;
+end//
+create procedure `p1`()
+begin
+select a, f1() from t1;
+end//
+call p1()//
+a f1()
+1 2
+2 2
+drop procedure p1//
+drop table t1//
set GLOBAL query_cache_size=0;
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index c7d27a8e60d..6f9b4e41b22 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -549,6 +549,66 @@ select count(*) from t2 where x = 18446744073709551601;
count(*)
0
drop table t1,t2;
+create table t1 (x bigint unsigned not null primary key) engine=innodb;
+insert into t1(x) values (0xfffffffffffffff0);
+insert into t1(x) values (0xfffffffffffffff1);
+select * from t1;
+x
+18446744073709551600
+18446744073709551601
+select count(*) from t1 where x>0;
+count(*)
+2
+select count(*) from t1 where x=0;
+count(*)
+0
+select count(*) from t1 where x<0;
+count(*)
+0
+select count(*) from t1 where x < -16;
+count(*)
+0
+select count(*) from t1 where x = -16;
+count(*)
+0
+select count(*) from t1 where x > -16;
+count(*)
+2
+select count(*) from t1 where x = 18446744073709551601;
+count(*)
+1
+drop table t1;
+create table t1 (a bigint unsigned);
+create index t1i on t1(a);
+insert into t1 select 18446744073709551615;
+insert into t1 select 18446744073709551614;
+explain select * from t1 where a <> -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index t1i t1i 9 NULL 2 Using where; Using index
+select * from t1 where a <> -1;
+a
+18446744073709551614
+18446744073709551615
+explain select * from t1 where a > -1 or a < -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index t1i t1i 9 NULL 2 Using where; Using index
+select * from t1 where a > -1 or a < -1;
+a
+18446744073709551614
+18446744073709551615
+explain select * from t1 where a > -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index t1i t1i 9 NULL 2 Using where; Using index
+select * from t1 where a > -1;
+a
+18446744073709551614
+18446744073709551615
+explain select * from t1 where a < -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+select * from t1 where a < -1;
+a
+drop table t1;
set names latin1;
create table t1 (a char(10), b text, key (a)) character set latin1;
INSERT INTO t1 (a) VALUES
@@ -660,3 +720,27 @@ id status
59 C
60 C
DROP TABLE t1;
+CREATE TABLE t1 (a int, b int, primary key(a,b));
+INSERT INTO t1 VALUES
+(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3);
+CREATE VIEW v1 as SELECT a,b FROM t1 WHERE b=3;
+EXPLAIN SELECT a,b FROM t1 WHERE a < 2 and b=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index
+EXPLAIN SELECT a,b FROM v1 WHERE a < 2 and b=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index
+EXPLAIN SELECT a,b FROM t1 WHERE a < 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index
+EXPLAIN SELECT a,b FROM v1 WHERE a < 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index
+SELECT a,b FROM t1 WHERE a < 2 and b=3;
+a b
+1 3
+SELECT a,b FROM v1 WHERE a < 2 and b=3;
+a b
+1 3
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/r/rpl_ddl.result b/mysql-test/r/rpl_ddl.result
new file mode 100644
index 00000000000..3737883b694
--- /dev/null
+++ b/mysql-test/r/rpl_ddl.result
@@ -0,0 +1,1077 @@
+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;
+SET AUTOCOMMIT = 1;
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+DROP DATABASE IF EXISTS mysqltest3;
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE TABLE mysqltest1.t1 (f1 BIGINT) ENGINE= "InnoDB";
+INSERT INTO mysqltest1.t1 SET f1= 0;
+CREATE TABLE mysqltest1.t2 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t3 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t4 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t5 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t6 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE INDEX my_idx6 ON mysqltest1.t6(f1);
+CREATE TABLE mysqltest1.t7 (f1 BIGINT) ENGINE= "InnoDB";
+INSERT INTO mysqltest1.t7 SET f1= 0;
+CREATE TABLE mysqltest1.t8 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t9 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t10 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t11 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t12 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t13 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t14 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t15 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t16 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t17 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t18 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t19 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TEMPORARY TABLE mysqltest1.t23 (f1 BIGINT);
+SET AUTOCOMMIT = 0;
+use mysqltest1;
+
+-------- switch to slave --------
+SET AUTOCOMMIT = 0;
+use mysqltest1;
+
+-------- switch to master -------
+
+######## COMMIT ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 0 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+0
+
+-------- switch to master -------
+COMMIT;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+
+######## ROLLBACK ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 1 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+2
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+TEST-INFO: MASTER: The INSERT is not committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+TEST-INFO: SLAVE: The INSERT is not committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+
+######## SET AUTOCOMMIT=1 ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 1 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+2
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+1
+
+-------- switch to master -------
+SET AUTOCOMMIT=1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+2
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+2
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+2
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+2
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SET AUTOCOMMIT=0;
+
+######## START TRANSACTION ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 2 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+3
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+2
+
+-------- switch to master -------
+START TRANSACTION;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+3
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+3
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+3
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+3
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+
+######## BEGIN ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 3 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+4
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+3
+
+-------- switch to master -------
+BEGIN;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+4
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+4
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+4
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+4
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+
+######## DROP TABLE mysqltest1.t2 ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 4 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+5
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+4
+
+-------- switch to master -------
+DROP TABLE mysqltest1.t2;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+5
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+5
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+5
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+5
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW TABLES LIKE 't2';
+Tables_in_mysqltest1 (t2)
+
+-------- switch to slave --------
+SHOW TABLES LIKE 't2';
+Tables_in_mysqltest1 (t2)
+
+-------- switch to master -------
+
+######## DROP TEMPORARY TABLE mysqltest1.t23 ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 5 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+5
+
+-------- switch to master -------
+DROP TEMPORARY TABLE mysqltest1.t23;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+5
+
+-------- switch to master -------
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+5
+
+TEST-INFO: MASTER: The INSERT is not committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW TABLES LIKE 't23';
+Tables_in_mysqltest1 (t23)
+
+-------- switch to slave --------
+SHOW TABLES LIKE 't23';
+Tables_in_mysqltest1 (t23)
+
+-------- switch to master -------
+
+######## RENAME TABLE mysqltest1.t3 to mysqltest1.t20 ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 5 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+-------- switch to master -------
+RENAME TABLE mysqltest1.t3 to mysqltest1.t20;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW TABLES LIKE 't20';
+Tables_in_mysqltest1 (t20)
+t20
+
+-------- switch to slave --------
+SHOW TABLES LIKE 't20';
+Tables_in_mysqltest1 (t20)
+t20
+
+-------- switch to master -------
+
+######## ALTER TABLE mysqltest1.t4 ADD column f2 BIGINT ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 6 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+7
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+6
+
+-------- switch to master -------
+ALTER TABLE mysqltest1.t4 ADD column f2 BIGINT;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+7
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+7
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+7
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+7
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+describe mysqltest1.t4;
+Field Type Null Key Default Extra
+f1 bigint(20) YES NULL
+f2 bigint(20) YES NULL
+
+-------- switch to slave --------
+describe mysqltest1.t4;
+Field Type Null Key Default Extra
+f1 bigint(20) YES NULL
+f2 bigint(20) YES NULL
+
+-------- switch to master -------
+
+######## CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE= "InnoDB" ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 7 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+8
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+7
+
+-------- switch to master -------
+CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE= "InnoDB";
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+8
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+8
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+8
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+8
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+
+######## CREATE TEMPORARY TABLE mysqltest1.t22 (f1 BIGINT) ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 8 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+8
+
+-------- switch to master -------
+CREATE TEMPORARY TABLE mysqltest1.t22 (f1 BIGINT);
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+8
+
+-------- switch to master -------
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+8
+
+TEST-INFO: MASTER: The INSERT is not committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+
+######## TRUNCATE TABLE mysqltest1.t7 ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 8 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+-------- switch to master -------
+TRUNCATE TABLE mysqltest1.t7;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SELECT * FROM mysqltest1.t7;
+f1
+
+-------- switch to slave --------
+SELECT * FROM mysqltest1.t7;
+f1
+
+-------- switch to master -------
+
+######## LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 9 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+9
+
+-------- switch to master -------
+LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+UNLOCK TABLES;
+
+######## UNLOCK TABLES ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 10 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+11
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to master -------
+UNLOCK TABLES;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+11
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+TEST-INFO: MASTER: The INSERT is not committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+TEST-INFO: SLAVE: The INSERT is not committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+LOCK TABLES mysqltest1.t1 READ;
+
+######## UNLOCK TABLES ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 10 + 1;
+ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to master -------
+UNLOCK TABLES;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+TEST-INFO: MASTER: The INSERT is not committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+TEST-INFO: SLAVE: The INSERT is not committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ;
+
+######## UNLOCK TABLES ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 10 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+11
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+10
+
+-------- switch to master -------
+UNLOCK TABLES;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+11
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+11
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+11
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+11
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+
+######## DROP INDEX my_idx6 ON mysqltest1.t6 ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 11 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+12
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+11
+
+-------- switch to master -------
+DROP INDEX my_idx6 ON mysqltest1.t6;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+12
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+12
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+12
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+12
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW INDEX FROM mysqltest1.t6;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+
+-------- switch to slave --------
+SHOW INDEX FROM mysqltest1.t6;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+
+-------- switch to master -------
+
+######## CREATE INDEX my_idx5 ON mysqltest1.t5(f1) ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 12 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+13
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+12
+
+-------- switch to master -------
+CREATE INDEX my_idx5 ON mysqltest1.t5(f1);
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+13
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+13
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+13
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+13
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW INDEX FROM mysqltest1.t5;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t5 1 my_idx5 1 f1 A 0 NULL NULL YES BTREE
+
+-------- switch to slave --------
+SHOW INDEX FROM mysqltest1.t5;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t5 1 my_idx5 1 f1 A NULL NULL NULL YES BTREE
+
+-------- switch to master -------
+
+######## DROP DATABASE mysqltest2 ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 13 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+14
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+13
+
+-------- switch to master -------
+DROP DATABASE mysqltest2;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+14
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+14
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+14
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+14
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW DATABASES LIKE "mysqltest2";
+Database (mysqltest2)
+
+-------- switch to slave --------
+SHOW DATABASES LIKE "mysqltest2";
+Database (mysqltest2)
+
+-------- switch to master -------
+
+######## CREATE DATABASE mysqltest3 ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 14 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+15
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+14
+
+-------- switch to master -------
+CREATE DATABASE mysqltest3;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+15
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+15
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+15
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+15
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW DATABASES LIKE "mysqltest3";
+Database (mysqltest3)
+mysqltest3
+
+-------- switch to slave --------
+SHOW DATABASES LIKE "mysqltest3";
+Database (mysqltest3)
+mysqltest3
+
+-------- switch to master -------
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+DROP DATABASE IF EXISTS mysqltest3;
diff --git a/mysql-test/r/rpl_multi_update3.result b/mysql-test/r/rpl_multi_update3.result
new file mode 100644
index 00000000000..1b757b1400c
--- /dev/null
+++ b/mysql-test/r/rpl_multi_update3.result
@@ -0,0 +1,124 @@
+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;
+
+-------- Test for BUG#9361 --------
+CREATE TABLE t1 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (NULL, 0);
+INSERT INTO t1 SELECT NULL, 0 FROM t1;
+INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
+UPDATE t2, (SELECT a FROM t1) AS t SET t2.b = t.a+5 ;
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 6
+2 6
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 6
+2 6
+drop table t1,t2;
+
+-------- Test 1 for BUG#9361 --------
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+CREATE TABLE t1 (
+a1 char(30),
+a2 int,
+a3 int,
+a4 char(30),
+a5 char(30)
+);
+CREATE TABLE t2 (
+b1 int,
+b2 char(30)
+);
+INSERT INTO t1 VALUES ('Yes', 1, NULL, 'foo', 'bar');
+INSERT INTO t2 VALUES (1, 'baz');
+UPDATE t1 a, t2
+SET a.a1 = 'No'
+WHERE a.a2 =
+(SELECT b1
+FROM t2
+WHERE b2 = 'baz')
+AND a.a3 IS NULL
+AND a.a4 = 'foo'
+AND a.a5 = 'bar';
+SELECT * FROM t1;
+a1 a2 a3 a4 a5
+No 1 NULL foo bar
+SELECT * FROM t2;
+b1 b2
+1 baz
+DROP TABLE t1, t2;
+
+-------- Test 2 for BUG#9361 --------
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+CREATE TABLE t1 (
+i INT,
+j INT,
+x INT,
+y INT,
+z INT
+);
+CREATE TABLE t2 (
+i INT,
+k INT,
+x INT,
+y INT,
+z INT
+);
+CREATE TABLE t3 (
+j INT,
+k INT,
+x INT,
+y INT,
+z INT
+);
+INSERT INTO t1 VALUES ( 1, 2,13,14,15);
+INSERT INTO t2 VALUES ( 1, 3,23,24,25);
+INSERT INTO t3 VALUES ( 2, 3, 1,34,35), ( 2, 3, 1,34,36);
+UPDATE t1 AS a
+INNER JOIN t2 AS b
+ON a.i = b.i
+INNER JOIN t3 AS c
+ON a.j = c.j AND b.k = c.k
+SET a.x = b.x,
+a.y = b.y,
+a.z = (
+SELECT sum(z)
+FROM t3
+WHERE y = 34
+)
+WHERE b.x = 23;
+SELECT * FROM t1;
+i j x y z
+1 2 23 24 71
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result
index 7b3249d553a..64e09839f1b 100644
--- a/mysql-test/r/rpl_sp.result
+++ b/mysql-test/r/rpl_sp.result
@@ -21,7 +21,7 @@ set b = 8;
insert into t1 values (b);
insert into t1 values (unix_timestamp());
end|
-ERROR HY000: This routine is declared to be non-deterministic and to modify data and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
+ERROR HY000: This routine has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
show binlog events from 98|
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query 1 # create database if not exists mysqltest1
@@ -84,7 +84,7 @@ not deterministic
reads sql data
select * from mysqltest1.t1
alter procedure foo2 contains sql;
-ERROR HY000: This routine is declared to be non-deterministic and to modify data and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
+ERROR HY000: This routine has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
drop table t1;
create table t1 (a int);
create table t2 like t1;
@@ -97,7 +97,7 @@ grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1;
create procedure foo4()
deterministic
insert into t1 values (10);
-ERROR HY000: You do not have SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
+ERROR HY000: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
set global log_bin_trust_routine_creators=1;
create procedure foo4()
deterministic
@@ -109,7 +109,7 @@ call foo4();
Got one of the listed errors
show warnings;
Level Code Message
-Warning 1417 A routine failed and is declared to modify data and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
+Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
call foo3();
show warnings;
Level Code Message
@@ -117,7 +117,7 @@ call foo4();
Got one of the listed errors
show warnings;
Level Code Message
-Warning 1417 A routine failed and is declared to modify data and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
+Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
alter procedure foo4 sql security invoker;
call foo4();
show warnings;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 1c0321ac658..9f1ff2cd835 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -2073,7 +2073,7 @@ INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 1 as rnd1 from t1 where rand() > 2;
rnd1
DROP TABLE t1;
-CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp(14) NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
+CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (200001,2,1,1,100,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\E$',''),(200002,2,2,1,101,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\C$',''),(200003,1,3,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,20020425060427,'c:',NULL);
CREATE TABLE t2 ( hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, sampletid smallint(5) unsigned default NULL, sampletime datetime default NULL, samplevalue bigint(20) unsigned default NULL, KEY idx1 (hmid,volid,sampletid,sampletime)) ENGINE=MyISAM;
INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12:00:01',35);
@@ -2699,3 +2699,6 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 3
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
DROP TABLE t1,t2;
+select x'10' + 0, X'10' + 0, b'10' + 0, B'10' + 0;
+x'10' + 0 X'10' + 0 b'10' + 0 B'10' + 0
+16 16 2 2
diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result
index ee72fde7324..4ace6f59411 100644
--- a/mysql-test/r/sp-security.result
+++ b/mysql-test/r/sp-security.result
@@ -194,3 +194,20 @@ use test;
drop database sptest;
delete from mysql.user where user='usera' or user='userb' or user='userc';
delete from mysql.procs_priv where user='usera' or user='userb' or user='userc';
+drop function if exists bug_9503;
+create database mysqltest//
+use mysqltest//
+create table t1 (s1 int)//
+grant select on t1 to user1@localhost//
+create function bug_9503 () returns int sql security invoker begin declare v int;
+select min(s1) into v from t1; return v; end//
+use mysqltest;
+select bug_9503();
+ERROR 42000: execute command denied to user 'user1'@'localhost' for routine 'mysqltest.bug_9503'
+grant execute on function bug_9503 to user1@localhost;
+do 1;
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost;
+drop function bug_9503;
+use test;
+drop database mysqltest;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index bf6a4dbf68c..ed858ba27ee 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -1133,8 +1133,6 @@ end|
select f5(1)|
f5(1)
1
-select f5(2)|
-ERROR HY000: Table 't1' was not locked with LOCK TABLES
create function f6() returns int
begin
declare n int;
@@ -3174,4 +3172,56 @@ a1 a2 a3 data data2 data3
DROP PROCEDURE bug6866;
DROP VIEW tv|
DROP TABLE tt1, tt2, tt3|
+DROP PROCEDURE IF EXISTS bug10136|
+create table t3 ( name char(5) not null primary key, val float not null)|
+insert into t3 values ('aaaaa', 1), ('bbbbb', 2), ('ccccc', 3)|
+create procedure bug10136()
+begin
+declare done int default 3;
+repeat
+select * from t3;
+set done = done - 1;
+until done <= 0 end repeat;
+end|
+call bug10136()|
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+call bug10136()|
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+call bug10136()|
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+drop procedure bug10136|
+drop table t3|
drop table t1,t2;
diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result
index 047711bb736..6077087ab87 100644
--- a/mysql-test/r/sp_trans.result
+++ b/mysql-test/r/sp_trans.result
@@ -8,17 +8,13 @@ end|
set autocommit=0|
insert t1 values (2)|
call bug8850()|
-ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
commit|
select * from t1|
a
-2
call bug8850()|
-ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
set autocommit=1|
select * from t1|
a
-2
drop table t1|
drop procedure bug8850|
drop function if exists bug10015_1|
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index c5ba4d15a50..392bdda32e3 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -402,4 +402,22 @@ a\b a\"b a'\b a'\"b
SELECT "a\\b", "a\\\'b", "a""\\b", "a""\\\'b";
a\b a\'b a"\b a"\'b
a\b a\'b a"\b a"\'b
+set session sql_mode = 'NO_ENGINE_SUBSTITUTION';
+create table t1 (a int) engine=isam;
+ERROR HY000: The 'ISAM' feature is disabled; you need MySQL built with 'ISAM' to have it working
+show create table t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
+set session sql_mode = '';
+create table t1 (a int) engine=isam;
+Warnings:
+Warning 1266 Using storage engine MyISAM for table 't1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
SET @@SQL_MODE=@OLD_SQL_MODE;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 6703147c635..400a2be01f1 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1025,7 +1025,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select sql_no_cache (select sql_no_cache ecrypt(_latin1'test') AS `ENCRYPT('test')` from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
+Note 1003 select sql_no_cache (select sql_no_cache encrypt(_latin1'test') AS `ENCRYPT('test')` from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
@@ -2816,3 +2816,24 @@ select * from t1;
EMPNUM
E1
DROP TABLE t1,t2;
+CREATE TABLE t1(select_id BIGINT, values_id BIGINT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TABLE t2 (select_id BIGINT, values_id BIGINT,
+PRIMARY KEY(select_id,values_id));
+INSERT INTO t2 VALUES (0, 1), (0, 2), (0, 3), (1, 5);
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+WHERE select_id IN (1, 0));
+values_id
+1
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+WHERE select_id BETWEEN 0 AND 1);
+values_id
+1
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+WHERE select_id = 0 OR select_id = 1);
+values_id
+1
+DROP TABLE t1, t2;
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 996a692d531..0bb1fd1d550 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -482,3 +482,12 @@ i k ts
1 1 0000-00-00 00:00:00
2 2 0000-00-00 00:00:00
drop table t1, t2;
+drop function if exists bug5893;
+create table t1 (col1 int, col2 int);
+insert into t1 values (1, 2);
+create function bug5893 () returns int return 5;
+create trigger t1_bu before update on t1 for each row set new.col1= bug5893();
+drop function bug5893;
+update t1 set col2 = 4;
+ERROR 42000: FUNCTION test.bug5893 does not exist
+drop table t1;
diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result
index 4d9bc0c7fe1..4aa8587d6e1 100644
--- a/mysql-test/r/type_bit.result
+++ b/mysql-test/r/type_bit.result
@@ -466,3 +466,90 @@ select a+0 from t1;
a+0
255
drop table t1;
+create table t1 (a bit(7));
+insert into t1 values (120), (0), (111);
+select a+0 from t1 union select a+0 from t1;
+a+0
+120
+0
+111
+select a+0 from t1 union select NULL;
+a+0
+120
+0
+111
+NULL
+select NULL union select a+0 from t1;
+NULL
+NULL
+120
+0
+111
+create table t2 select a from t1 union select a from t1;
+select a+0 from t2;
+a+0
+120
+0
+111
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` bit(7) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1, t2;
+create table t1 (id1 int(11), b1 bit(1));
+create table t2 (id2 int(11), b2 bit(1));
+insert into t1 values (1, 1), (2, 0), (3, 1);
+insert into t2 values (2, 1), (3, 0), (4, 0);
+create algorithm=undefined view v1 as
+select b1+0, b2+0 from t1, t2 where id1 = id2 and b1 = 0
+union
+select b1+0, b2+0 from t1, t2 where id1 = id2 and b2 = 1;
+select * from v1;
+b1+0 b2+0
+0 1
+drop table t1, t2;
+drop view v1;
+create table t1(a bit(4));
+insert into t1(a) values (1), (2), (5), (4), (3);
+insert into t1 select * from t1;
+select a+0 from t1;
+a+0
+1
+2
+5
+4
+3
+1
+2
+5
+4
+3
+drop table t1;
+create table t1 (a1 int(11), b1 bit(2));
+create table t2 (a2 int(11), b2 bit(2));
+insert into t1 values (1, 1), (2, 0), (3, 1), (4, 2);
+insert into t2 values (2, 1), (3, 0), (4, 1), (5, 2);
+select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2;
+a1 a2 b1+0 b2+0
+2 2 0 1
+3 3 1 0
+4 4 2 1
+select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2 order by a1;
+a1 a2 b1+0 b2+0
+2 2 0 1
+3 3 1 0
+4 4 2 1
+select a1, a2, b1+0, b2+0 from t1 join t2 on b1 = b2;
+a1 a2 b1+0 b2+0
+1 2 1 1
+3 2 1 1
+2 3 0 0
+1 4 1 1
+3 4 1 1
+4 5 2 2
+select sum(a1), b1+0, b2+0 from t1 join t2 on b1 = b2 group by b1 order by 1;
+sum(a1) b1+0 b2+0
+2 0 0
+4 2 2
+8 1 1
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index b406dbab82f..79943df18c5 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -928,3 +928,9 @@ select * from t1 where a = -0.00;
a
0.00
drop table t1;
+create table t1 (col1 bigint default -9223372036854775808);
+insert into t1 values (default);
+select * from t1;
+col1
+-9223372036854775808
+drop table t1;
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 9b851d74a12..61ed6bbabf3 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -99,6 +99,14 @@ drop table t1;
create table t1 (t2 timestamp(2), t4 timestamp(4), t6 timestamp(6),
t8 timestamp(8), t10 timestamp(10), t12 timestamp(12),
t14 timestamp(14));
+Warnings:
+Warning 1287 'TIMESTAMP(2)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(4)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(6)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(8)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(10)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(12)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(14)' is deprecated; use 'TIMESTAMP' instead
insert t1 values (0,0,0,0,0,0,0),
("1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59",
"1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59",
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index d83952e118b..b0055346d61 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -58,7 +58,7 @@ ushows int(10) unsigned DEFAULT '0' NOT NULL,
clicks int(10) unsigned DEFAULT '0' NOT NULL,
iclicks int(10) unsigned DEFAULT '0' NOT NULL,
uclicks int(10) unsigned DEFAULT '0' NOT NULL,
-ts timestamp(14),
+ts timestamp,
PRIMARY KEY (place_id,ts)
);
INSERT INTO t1 (place_id,shows,ishows,ushows,clicks,iclicks,uclicks,ts)
@@ -75,7 +75,7 @@ client varchar(255) NOT NULL default '',
replyto varchar(255) NOT NULL default '',
subject varchar(100) NOT NULL default '',
timestamp int(10) unsigned NOT NULL default '0',
-tstamp timestamp(14) NOT NULL,
+tstamp timestamp NOT NULL,
status int(3) NOT NULL default '0',
type varchar(15) NOT NULL default '',
assignment int(10) unsigned NOT NULL default '0',
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 84be086ae37..4c1db618b4b 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -1726,3 +1726,127 @@ sum(a)
drop procedure p1;
drop view v1;
drop table t1;
+CREATE TABLE t1(a char(2) primary key, b char(2));
+CREATE TABLE t2(a char(2), b char(2), index i(a));
+INSERT INTO t1 VALUES ('a','1'), ('b','2');
+INSERT INTO t2 VALUES ('a','5'), ('a','6'), ('b','5'), ('b','6');
+CREATE VIEW v1 AS
+SELECT t1.b as c, t2.b as d FROM t1,t2 WHERE t1.a=t2.a;
+SELECT d, c FROM v1 ORDER BY d,c;
+d c
+5 1
+5 2
+6 1
+6 2
+DROP VIEW v1;
+DROP TABLE t1, t2;
+create table t1 (s1 int);
+create view v1 as select sum(distinct s1) from t1;
+select * from v1;
+sum(distinct s1)
+NULL
+drop view v1;
+create view v1 as select avg(distinct s1) from t1;
+select * from v1;
+avg(distinct s1)
+NULL
+drop view v1;
+drop table t1;
+create view v1 as select cast(1 as decimal);
+select * from v1;
+cast(1 as decimal)
+1.00
+drop view v1;
+create table t1(f1 int);
+create table t2(f2 int);
+insert into t1 values(1),(2),(3);
+insert into t2 values(1),(2),(3);
+create view v1 as select * from t1,t2 where f1=f2;
+create table t3 (f1 int, f2 int);
+insert into t3 select * from v1 order by 1;
+select * from t3;
+f1 f2
+1 1
+2 2
+3 3
+drop view v1;
+drop table t1,t2,t3;
+create view v1 as select '\\','\\shazam';
+select * from v1;
+\ \shazam
+\ \shazam
+drop view v1;
+create view v1 as select '\'','\shazam';
+select * from v1;
+' shazam
+' shazam
+drop view v1;
+create view v1 as select 'k','K';
+select * from v1;
+k My_exp_K
+k K
+drop view v1;
+create table t1 (s1 int);
+create view v1 as select s1, 's1' from t1;
+select * from v1;
+s1 My_exp_s1
+drop view v1;
+create view v1 as select 's1', s1 from t1;
+select * from v1;
+My_exp_s1 s1
+drop view v1;
+create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
+select * from v1;
+My_exp_1_s1 s1 My_exp_s1
+drop view v1;
+create view v1 as select 1 as My_exp_s1, 's1', s1 from t1;
+select * from v1;
+My_exp_s1 My_exp_1_s1 s1
+drop view v1;
+create view v1 as select 1 as s1, 's1', 's1' from t1;
+select * from v1;
+s1 My_exp_s1 My_exp_1_s1
+drop view v1;
+create view v1 as select 's1', 's1', 1 as s1 from t1;
+select * from v1;
+My_exp_1_s1 My_exp_s1 s1
+drop view v1;
+create view v1 as select s1, 's1', 's1' from t1;
+select * from v1;
+s1 My_exp_s1 My_exp_1_s1
+drop view v1;
+create view v1 as select 's1', 's1', s1 from t1;
+select * from v1;
+My_exp_1_s1 My_exp_s1 s1
+drop view v1;
+create view v1 as select 1 as s1, 's1', s1 from t1;
+ERROR 42S21: Duplicate column name 's1'
+create view v1 as select 's1', s1, 1 as s1 from t1;
+ERROR 42S21: Duplicate column name 's1'
+drop table t1;
+create view v1(k, K) as select 1,2;
+ERROR 42S21: Duplicate column name 'K'
+create view v1 as SELECT TIME_FORMAT(SEC_TO_TIME(3600),'%H:%i') as t;
+select * from v1;
+t
+01:00
+drop view v1;
+create table t1 (f1 date);
+insert into t1 values ('2005-01-01'),('2005-02-02');
+create view v1 as select * from t1;
+select * from v1 where f1='2005.02.02';
+f1
+2005-02-02
+select * from v1 where '2005.02.02'=f1;
+f1
+2005-02-02
+drop view v1;
+drop table t1;
+CREATE VIEW v1 AS SELECT ENCRYPT("dhgdhgd");
+SELECT * FROM v1;
+drop view v1;
+CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1);
+SELECT * FROM v1;
+SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1)
+dkjhgd
+drop view v1;
diff --git a/mysql-test/t/alias.test b/mysql-test/t/alias.test
index 986af339456..cfa8ec7f18a 100644
--- a/mysql-test/t/alias.test
+++ b/mysql-test/t/alias.test
@@ -30,7 +30,7 @@ CREATE TABLE t1 (
prov_hdl_nr int(11) NOT NULL default '0',
auto_wirknetz varchar(50) default NULL,
auto_billing varchar(50) default NULL,
- touch timestamp(14) NOT NULL,
+ touch timestamp NOT NULL,
kategorie varchar(50) default NULL,
kundentyp varchar(20) NOT NULL default '',
sammel_rech_msisdn varchar(30) NOT NULL default '',
@@ -61,8 +61,9 @@ INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05
INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
# This died because we used the field Kundentyp twice
-
+--disable_ps_protocol
SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie;
+--enable_ps_protocol
drop table t1;
diff --git a/mysql-test/t/bdb_cache.test b/mysql-test/t/bdb_cache.test
index 0082c83faff..401456711ac 100644
--- a/mysql-test/t/bdb_cache.test
+++ b/mysql-test/t/bdb_cache.test
@@ -14,15 +14,13 @@ insert into t1 values (1),(2),(3);
select * from t1;
show status like "Qcache_queries_in_cache";
drop table t1;
-commit;
set autocommit=1;
-begin;
create table t1 (a int not null) engine=bdb;
+begin;
insert into t1 values (1),(2),(3);
select * from t1;
show status like "Qcache_queries_in_cache";
drop table t1;
-commit;
create table t1 (a int not null) engine=bdb;
create table t2 (a int not null) engine=bdb;
create table t3 (a int not null) engine=bdb;
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index f2cfce9085d..e942333d5fe 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -111,6 +111,17 @@ explain extended SELECT
SHOW CREATE TABLE t1;
DROP TABLE t1;
+# Test for BUG#10151
+SELECT 'case+union+test'
+UNION
+SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END;
+
+SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END;
+
+SELECT 'case+union+test'
+UNION
+SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
+
#
# Tests for bug #9939: conversion of the arguments for COALESCE and IFNULL
#
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index cafecd6000d..356b69daf38 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -168,3 +168,20 @@ create table t1(s1 time);
insert into t1 values ('11:11:11');
select cast(s1 as decimal(7,2)) from t1;
drop table t1;
+
+#
+# Test for bug #11283: field conversion from varchar, and text types to decimal
+#
+
+CREATE TABLE t1 (v varchar(10), tt tinytext, t text,
+ mt mediumtext, lt longtext);
+INSERT INTO t1 VALUES ('1.01', '2.02', '3.03', '4.04', '5.05');
+
+SELECT CAST(v AS DECIMAL), CAST(tt AS DECIMAL), CAST(t AS DECIMAL),
+ CAST(mt AS DECIMAL), CAST(lt AS DECIMAL) from t1;
+
+DROP TABLE t1;
+# Bug @10237 (CAST(NULL DECIMAL) crashes server)
+#
+select cast(NULL as decimal(6)) as t1;
+
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 3c49b2a47f7..343b7c867e7 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -746,3 +746,45 @@ insert into t1 values (2,'Durban');
select * from t1 where city = 'Durban';
select * from t1 where city = 'Durban ';
drop table t1;
+
+#
+# Test for bug #11167: join for utf8 varchar value longer than 255 bytes
+#
+
+SET NAMES UTF8;
+
+CREATE TABLE t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `country` varchar(100) NOT NULL default '',
+ `shortcode` varchar(100) NOT NULL default '',
+ `operator` varchar(100) NOT NULL default '',
+ `momid` varchar(30) NOT NULL default '',
+ `keyword` varchar(160) NOT NULL default '',
+ `content` varchar(160) NOT NULL default '',
+ `second_token` varchar(160) default NULL,
+ `gateway_id` int(11) NOT NULL default '0',
+ `created` datetime NOT NULL default '0000-00-00 00:00:00',
+ `msisdn` varchar(15) NOT NULL default '',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `MSCCSPK_20030521130957121` (`momid`),
+ KEY `IX_mobile_originated_message_keyword` (`keyword`),
+ KEY `IX_mobile_originated_message_created` (`created`),
+ KEY `IX_mobile_originated_message_support` (`msisdn`,`momid`,`keyword`,`gateway_id`,`created`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO t1 VALUES
+(1,'blah','464','aaa','fkc1c9ilc20x0hgae7lx6j09','ERR','ERR Имри.Ðфимим.Ðеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ðд.Д имдимримрад.Ðдимримримрмдиримримримр м.Дадимфшьмримд им.Ðдимимрн имадми','ИМРИ.ÐФИМИМ.ÐЕИМИМРИМДМРИМРМРИРОР',3,'2005-06-01 17:30:43','1234567890'),
+(2,'blah','464','aaa','haxpl2ilc20x00bj4tt2m5ti','11','11 g','G',3,'2005-06-02 22:43:10','1234567890');
+
+CREATE TABLE t2 (
+ `msisdn` varchar(15) NOT NULL default '',
+ `operator_id` int(11) NOT NULL default '0',
+ `created` datetime NOT NULL default '0000-00-00 00:00:00',
+ UNIQUE KEY `PK_user` (`msisdn`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO t2 VALUES ('1234567890',2,'2005-05-24 13:53:25');
+
+SELECT content, t2.msisdn FROM t1, t2 WHERE t1.msisdn = '1234567890';
+
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index 2acf69dad76..3c4d5dc93da 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -253,9 +253,9 @@ insert into t2 values (3, 1, 'xxbuz');
select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode);
#
-# bug with many short (< ft_min_word_len) words in boolean search
+# Bug #7858: bug with many short (< ft_min_word_len) words in boolean search
#
-select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode);
+select * from t2 where match name against ('*a*b*c*d*e*f*' in boolean mode);
drop table t1,t2;
#
diff --git a/mysql-test/t/func_date_add.test b/mysql-test/t/func_date_add.test
index 93c77daf86e..29c13793b78 100644
--- a/mysql-test/t/func_date_add.test
+++ b/mysql-test/t/func_date_add.test
@@ -11,7 +11,7 @@ CREATE TABLE t1 (
group_id int(10) unsigned DEFAULT '0' NOT NULL,
hits int(10) unsigned DEFAULT '0' NOT NULL,
sessions int(10) unsigned DEFAULT '0' NOT NULL,
- ts timestamp(14),
+ ts timestamp,
PRIMARY KEY (visitor_id,group_id)
)/*! engine=MyISAM */;
INSERT INTO t1 VALUES (465931136,7,2,2,20000318160952);
diff --git a/mysql-test/t/func_default.test b/mysql-test/t/func_default.test
index 6ae9f088f92..af7ebcf588b 100644
--- a/mysql-test/t/func_default.test
+++ b/mysql-test/t/func_default.test
@@ -16,4 +16,14 @@ explain select * from t1 where str <> default(str);
#show create table from t1;
#insert into t2 select select default(str), default(strnull), default(intg), default(rel) from t1;
-drop table t1; \ No newline at end of file
+drop table t1;
+
+#
+# Bug #11314 (HAVING DEFAULT() hangs)
+#
+CREATE TABLE t1 (id int(11), s varchar(20));
+INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
+--error 1364
+SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
+DROP TABLE t1;
+
diff --git a/mysql-test/t/func_encrypt.test b/mysql-test/t/func_encrypt.test
index fe81a814dda..52aca7f9dcb 100644
--- a/mysql-test/t/func_encrypt.test
+++ b/mysql-test/t/func_encrypt.test
@@ -59,6 +59,22 @@ select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("he
select des_decrypt(des_encrypt("hello"),'default_password');
select des_decrypt(des_encrypt("hello",4),'password4');
+# Test use of invalid parameters
+select des_encrypt("hello",10);
+select des_encrypt(NULL);
+select des_encrypt(NULL, 10);
+select des_encrypt(NULL, NULL);
+select des_encrypt(10, NULL);
+select des_encrypt("hello", NULL);
+
+select des_decrypt("hello",10);
+select des_decrypt(NULL);
+select des_decrypt(NULL, 10);
+select des_decrypt(NULL, NULL);
+select des_decrypt(10, NULL);
+select des_decrypt("hello", NULL);
+
+
# Test flush
SET @a=des_decrypt(des_encrypt("hello"));
flush des_key_file;
diff --git a/mysql-test/t/func_encrypt_nossl.test b/mysql-test/t/func_encrypt_nossl.test
new file mode 100644
index 00000000000..0e9d93f5968
--- /dev/null
+++ b/mysql-test/t/func_encrypt_nossl.test
@@ -0,0 +1,36 @@
+-- source include/not_openssl.inc
+
+#
+# Test output from des_encrypt and des_decrypt when server is
+# compiled without openssl suuport
+#
+select des_encrypt("test", 'akeystr');
+select des_encrypt("test", 1);
+select des_encrypt("test", 9);
+select des_encrypt("test", 100);
+select des_encrypt("test", NULL);
+select des_decrypt("test", 'anotherkeystr');
+select des_decrypt(1, 1);
+select des_decrypt(des_encrypt("test", 'thekey'));
+
+
+#
+# Test default keys
+#
+select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello"));
+select des_decrypt(des_encrypt("hello",4));
+select des_decrypt(des_encrypt("hello",'test'),'test');
+select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password'));
+select des_decrypt(des_encrypt("hello"),'default_password');
+select des_decrypt(des_encrypt("hello",4),'password4');
+
+# Test flush
+SET @a=des_decrypt(des_encrypt("hello"));
+flush des_key_file;
+select @a = des_decrypt(des_encrypt("hello"));
+
+# Test usage of wrong password
+select hex("hello");
+select hex(des_decrypt(des_encrypt("hello",4),'password2'));
+select hex(des_decrypt(des_encrypt("hello","hidden")));
+
diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test
index 37556984f68..03590dea8d1 100644
--- a/mysql-test/t/func_if.test
+++ b/mysql-test/t/func_if.test
@@ -75,3 +75,15 @@ SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, t
SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord DESC;
DROP TABLE t1;
+
+#
+# Test for bug #11142: evaluation of NULLIF when the first argument is NULL
+#
+
+CREATE TABLE t1 (a CHAR(10));
+INSERT INTO t1 VALUES ('aaa'), (NULL), (''), ('bbb');
+
+SELECT a, NULLIF(a,'') FROM t1;
+SELECT a, NULLIF(a,'') FROM t1 WHERE NULLIF(a,'') IS NULL;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index 03057af6911..da4b8335e07 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -84,3 +84,10 @@ drop table t1;
# Bug #10083 (round doesn't increase decimals)
#
select round(150, 2);
+
+#
+# Bug @10632 (Ceiling function returns wrong answer)
+#
+select ceil(0.09);
+select ceil(0.000000000000000009);
+
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 728f0e2c084..617de1b3cc5 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -128,7 +128,7 @@ CREATE TABLE t1 (
program int(10) unsigned default NULL,
bugdesc text,
created datetime default NULL,
- modified timestamp(14) NOT NULL,
+ modified timestamp NOT NULL,
bugstatus int(10) unsigned default NULL,
submitter int(10) unsigned default NULL
) ENGINE=MyISAM;
@@ -529,3 +529,17 @@ DROP TABLE t1, t2;
#
select field(0,NULL,1,0), field("",NULL,"bar",""), field(0.0,NULL,1.0,0.0);
select field(NULL,1,2,NULL), field(NULL,1,2,0);
+
+#
+# Bug #10124: access by integer index with a string key that is not a number
+#
+
+CREATE TABLE t1 (str varchar(20) PRIMARY KEY);
+CREATE TABLE t2 (num int primary key);
+INSERT INTO t1 VALUES ('notnumber');
+INSERT INTO t2 VALUES (0), (1);
+
+SELECT * FROM t1, t2 WHERE num=str;
+SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6);
+
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 6ca29ccded2..66ff460fc61 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -211,7 +211,7 @@ drop table t1;
CREATE TABLE t1 ( start datetime default NULL);
INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00');
-CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL);
+CREATE TABLE t2 ( ctime1 timestamp NOT NULL, ctime2 timestamp NOT NULL);
INSERT INTO t2 VALUES (20021029165106,20021105164731);
CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 21d5abcc287..9f920a1dd83 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -1,3 +1,4 @@
+
# Initialise
--disable_warnings
drop table if exists t1,t2,t3;
@@ -134,7 +135,7 @@ CREATE TABLE t1 (
bug_severity enum('blocker','critical','major','normal','minor','trivial','enhancement') DEFAULT 'blocker' NOT NULL,
bug_status enum('','NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','CLOSED') DEFAULT 'NEW' NOT NULL,
creation_ts datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
- delta_ts timestamp(14),
+ delta_ts timestamp,
short_desc mediumtext,
long_desc mediumtext,
op_sys enum('All','Windows 3.1','Windows 95','Windows 98','Windows NT','Windows 2000','Linux','other') DEFAULT 'All' NOT NULL,
@@ -524,7 +525,7 @@ select min(b) from t1;
drop table t1;
#
-# Test for bug #11088: GROUP BY a BLOB colimn with COUNT(DISTINCT column1)
+# Test for bug #11088: GROUP BY a BLOB column with COUNT(DISTINCT column1)
#
CREATE TABLE t1 (id int PRIMARY KEY, user_id int, hostname longtext);
@@ -539,3 +540,43 @@ SELECT hostname, COUNT(DISTINCT user_id) as no FROM t1
WHERE hostname LIKE '%aol%'
GROUP BY hostname;
+DROP TABLE t1;
+
+#
+# Test for bug #8614: GROUP BY 'const' with DISTINCT
+#
+
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,2), (1,3);
+SELECT a, b FROM t1 GROUP BY 'const';
+SELECT DISTINCT a, b FROM t1 GROUP BY 'const';
+
+DROP TABLE t1;
+
+#
+# Test for bug #11385: GROUP BY for datetime converted to decimals
+#
+
+CREATE TABLE t1 (id INT, dt DATETIME);
+INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
+INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
+INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
+INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
+SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f;
+
+DROP TABLE t1;
+
+#
+# Test for bug #11295: GROUP BY a BLOB column with COUNT(DISTINCT column1)
+# when the BLOB column takes NULL values
+#
+
+CREATE TABLE t1 (id varchar(20) NOT NULL);
+INSERT INTO t1 VALUES ('trans1'), ('trans2');
+CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL);
+INSERT INTO t2 VALUES ('trans1', 'a problem');
+
+SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment
+ FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY comment;
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
index 76f959b983b..6731be615fd 100644
--- a/mysql-test/t/group_min_max.test
+++ b/mysql-test/t/group_min_max.test
@@ -482,7 +482,6 @@ select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
-
--
-- DISTINCT queries
--
@@ -526,6 +525,7 @@ select distinct a1,a1 from t1;
select distinct a2,a1,a2,a1 from t1;
select distinct t1.a1,t2.a1 from t1,t2;
+
--
-- DISTINCT queries with GROUP-BY
--
@@ -641,6 +641,17 @@ explain select a1,a2,count(a2) from t1 group by a1,a2,b;
explain select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
+#
+# BUG#11044: DISTINCT or GROUP BY queries with equality predicates instead of MIN/MAX.
+#
+
+explain select a1 from t1 where a2 = 'b' group by a1;
+select a1 from t1 where a2 = 'b' group by a1;
+
+explain select distinct a1 from t1 where a2 = 'b';
+select distinct a1 from t1 where a2 = 'b';
+
+
drop table t1;
drop table t2;
drop table t3;
diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test
index 46669dd2b8f..21ac69ef3a1 100644
--- a/mysql-test/t/heap_hash.test
+++ b/mysql-test/t/heap_hash.test
@@ -169,6 +169,8 @@ explain select * from t1 where a='aaac';
explain select * from t1 where a='aaad';
insert into t1 select * from t1;
+# avoid statistics differences between normal and ps-protocol tests
+flush tables;
explain select * from t1 where a='aaaa';
explain select * from t1 where a='aaab';
explain select * from t1 where a='aaac';
diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test
index 5ac91f1f8b1..42175a757c2 100644
--- a/mysql-test/t/index_merge.test
+++ b/mysql-test/t/index_merge.test
@@ -310,7 +310,8 @@ update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500;
# The next query will not use index i7 in intersection if the OS doesn't
# support file sizes > 2GB. (ha_myisam::ref_length depends on this and index
# scan cost estimates depend on ha_myisam::ref_length)
---replace_result "4,4,4,4,4,4,4" X "4,4,4,4,4,4" X "i6,i7" "i6,i7?" "i6" "i6,i7?" 7 # 16 # 18 #
+--replace_column 9 #
+--replace_result "4,4,4,4,4,4,4" X "4,4,4,4,4,4" X "i6,i7" "i6,i7?" "i6" "i6,i7?"
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
diff --git a/mysql-test/t/index_merge_innodb.test b/mysql-test/t/index_merge_innodb.test
index 5e270c161a2..c10ce3b9688 100644
--- a/mysql-test/t/index_merge_innodb.test
+++ b/mysql-test/t/index_merge_innodb.test
@@ -120,3 +120,14 @@ select count(*) from t1 where
drop table t1,t2;
+# Test for BUG#8441
+create table t1 (
+ id1 int,
+ id2 date ,
+ index idx2 (id1,id2),
+ index idx1 (id2)
+) engine = innodb;
+insert into t1 values(1,'20040101'), (2,'20040102');
+select * from t1 where id1 = 1 and id2= '20040101';
+drop table t1;
+
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
index 7302b3e5e58..e03bea5899a 100644
--- a/mysql-test/t/information_schema.test
+++ b/mysql-test/t/information_schema.test
@@ -542,3 +542,18 @@ connection default;
drop user user1@localhost, user2@localhost, user3@localhost, user4@localhost;
use test;
drop database mysqltest;
+
+#
+# Bug #11055 information_schema: routines.sql_data_access has wrong value
+#
+create procedure p1 () modifies sql data set @a = 5;
+create procedure p2 () set @a = 5;
+select sql_data_access from information_schema.routines
+where specific_name like 'p%';
+drop procedure p1;
+drop procedure p2;
+
+#
+# Bug #9434 SHOW CREATE DATABASE information_schema;
+#
+show create database information_schema;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 7b27d589ec3..485eeec05d9 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -596,7 +596,6 @@ show tables from mysqltest;
set autocommit=0;
create table t1 (a int not null) engine= innodb;
insert into t1 values(1),(2);
---error 1192
truncate table t1;
commit;
truncate table t1;
@@ -661,9 +660,9 @@ CREATE TABLE t1 (
cname char(15) NOT NULL default '',
carrier_id smallint(6) NOT NULL default '0',
privacy tinyint(4) NOT NULL default '0',
- last_mod_date timestamp(14) NOT NULL,
+ last_mod_date timestamp NOT NULL,
last_mod_id smallint(6) NOT NULL default '0',
- last_app_date timestamp(14) NOT NULL,
+ last_app_date timestamp NOT NULL,
last_app_id smallint(6) default '-1',
version smallint(6) NOT NULL default '0',
assigned_scps int(11) default '0',
@@ -680,9 +679,9 @@ CREATE TABLE t2 (
cname char(15) NOT NULL default '',
carrier_id smallint(6) NOT NULL default '0',
privacy tinyint(4) NOT NULL default '0',
- last_mod_date timestamp(14) NOT NULL,
+ last_mod_date timestamp NOT NULL,
last_mod_id smallint(6) NOT NULL default '0',
- last_app_date timestamp(14) NOT NULL,
+ last_app_date timestamp NOT NULL,
last_app_id smallint(6) default '-1',
version smallint(6) NOT NULL default '0',
assigned_scps int(11) default '0',
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 40dc4e20093..a6468c52645 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -164,3 +164,26 @@ INSERT INTO t1 (SEQ, NO) SELECT "1" AS SEQ, IF(MAX(NO) IS NULL, 0, MAX(NO)) + 1
select SQL_BUFFER_RESULT * from t1 WHERE (SEQ = 1);
drop table t1;
+#
+# Bug#10886 - Have to restore default values after update ON DUPLICATE KEY
+#
+create table t1 (f1 int);
+create table t2 (ff1 int unique, ff2 int default 1);
+insert into t1 values (1),(1),(2);
+insert into t2(ff1) select f1 from t1 on duplicate key update ff2=ff2+1;
+select * from t2;
+drop table t1, t2;
+#
+# BUGS #9728 - 'Decreased functionality in "on duplicate key update"'
+# #8147 - 'a column proclaimed ambigous in INSERT ... SELECT .. ON
+# DUPLICATE'
+#
+create table t1 (a int unique);
+create table t2 (a int, b int);
+insert into t1 values (1),(2);
+insert into t2 values (1,2);
+select * from t1;
+insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b;
+select * from t1;
+drop table t1;
+drop table t2;
diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test
index f5857840588..7653fd8dd42 100644
--- a/mysql-test/t/insert_update.test
+++ b/mysql-test/t/insert_update.test
@@ -1,5 +1,5 @@
--disable_warnings
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1, t2;
--enable_warnings
CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
diff --git a/mysql-test/t/join_nested.test b/mysql-test/t/join_nested.test
index 9591f1fa7ed..992217d0391 100644
--- a/mysql-test/t/join_nested.test
+++ b/mysql-test/t/join_nested.test
@@ -752,3 +752,21 @@ EXPLAIN SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
DROP TABLE t1,t2,t3;
+
+#
+# Test for bug #11284: empty table in a nested left join
+#
+
+CREATE TABLE t1 (c11 int);
+CREATE TABLE t2 (c21 int);
+CREATE TABLE t3 (c31 int);
+
+INSERT INTO t1 VALUES (4), (5);
+
+SELECT * FROM t1 LEFT JOIN t2 ON c11=c21;
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON c11=c21;
+
+SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON c21=c31) ON c11=c21;
+EXPLAIN SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON c21=c31) ON c11=c21;
+
+DROP TABLE t1,t2,t3;
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index 670e7433926..7dd35f164d5 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -698,4 +698,16 @@ SELECT * FROM v1 WHERE EMPNUM < 10;
DROP TABLE t1,t2;
+#
+# Test for bug #11285: false Item_equal on expression in outer join
+#
+
+CREATE TABLE t1 (c11 int);
+CREATE TABLE t2 (c21 int);
+INSERT INTO t1 VALUES (30), (40), (50);
+INSERT INTO t2 VALUES (300), (400), (500);
+
+SELECT * FROM t1 LEFT JOIN t2 ON (c11=c21 AND c21=30) WHERE c11=40;
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test
index cbda47ac864..43cff90332b 100644
--- a/mysql-test/t/lock_multi.test
+++ b/mysql-test/t/lock_multi.test
@@ -94,3 +94,15 @@ connection reader;
reap;
connection locker;
drop table t1;
+
+
+#
+# BUG#9998 - MySQL client hangs on USE "database"
+
+create table t1(a int);
+lock tables t1 write;
+connection reader;
+show columns from t1;
+connection locker;
+unlock tables;
+drop table t1;
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
index d30e5b65d8e..c1d9813ea39 100644
--- a/mysql-test/t/mysql.test
+++ b/mysql-test/t/mysql.test
@@ -30,5 +30,14 @@ select "Test 'go' command(vertical output) \G" as " ";
select "Test 'go' command \g" as " ";
--exec $MYSQL test -e 'select * from t1\g'
--enable_query_log
+drop table t1;
+#
+# BUG9998 - MySQL client hangs on USE "database"
+#
+create table t1(a int);
+lock tables t1 write;
+--exec $MYSQL -e 'use test; select database();'
+unlock tables;
drop table t1;
+
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 7a39fbdf5f6..ec49eec8b46 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -4,7 +4,8 @@
--disable_warnings
DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa;
drop database if exists mysqldump_test_db;
-drop view if exists v1;
+drop database if exists db1;
+drop view if exists v1, v2;
--enable_warnings
# XML output
@@ -563,3 +564,117 @@ CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES (1),(2),(3);
--exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test
DROP TABLE t1;
+
+#
+# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X)
+#
+
+create database db1;
+use db1;
+
+CREATE TABLE t2 (
+ a varchar(30) default NULL,
+ KEY a (a(5))
+);
+
+INSERT INTO t2 VALUES ('alfred');
+INSERT INTO t2 VALUES ('angie');
+INSERT INTO t2 VALUES ('bingo');
+INSERT INTO t2 VALUES ('waffle');
+INSERT INTO t2 VALUES ('lemon');
+create view v2 as select * from t2 where a like 'a%' with check option;
+--exec $MYSQL_DUMP --skip-comments db1
+drop table t2;
+drop view v2;
+drop database db1;
+#
+# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data
+#
+
+CREATE DATABASE mysqldump_test_db;
+USE mysqldump_test_db;
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+INSERT INTO t1 VALUES (1), (2);
+INSERT INTO t2 VALUES (1), (2);
+--exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db
+--exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db t1 t2
+--exec $MYSQL_DUMP --skip-comments --skip-create --xml --no-data mysqldump_test_db
+--exec $MYSQL_DUMP --skip-comments --skip-create --xml --no-data mysqldump_test_db t1 t2
+DROP TABLE t1, t2;
+DROP DATABASE mysqldump_test_db;
+
+#
+# Testing with tables and databases that don't exists
+# or contains illegal characters
+# (Bug #9358 mysqldump crashes if tablename starts with \)
+#
+create database mysqldump_test_db;
+use mysqldump_test_db;
+create table t1(a varchar(30) primary key, b int not null);
+create table t2(a varchar(30) primary key, b int not null);
+create table t3(a varchar(30) primary key, b int not null);
+
+--disable_query_log
+select '------ Testing with illegal table names ------' as test_sequence ;
+--enable_query_log
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\d-2-1.sql" 2>&1
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\t1" 2>&1
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\1" 2>&1
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\\1" 2>&1
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t/1" 2>&1
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1"
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T%1"
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T'1"
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1"
+
+--error 6
+--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_"
+
+--disable_query_log
+select '------ Testing with illegal database names ------' as test_sequence ;
+--enable_query_log
+--error 2
+--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_d 2>&1
+
+--error 2
+--exec $MYSQL_DUMP --compact --skip-comments "mysqld\ump_test_db" 2>&1
+
+drop table t1, t2, t3;
+drop database mysqldump_test_db;
+use test;
+
+#
+# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly
+#
+
+create table t1 (a int(10));
+create table t2 (pk int primary key auto_increment,
+a int(10), b varchar(30), c datetime, d blob, e text);
+insert into t1 values (NULL), (10), (20);
+insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thirty");
+--exec $MYSQL_DUMP --skip-comments --xml --no-create-info test
+drop table t1, t2;
+
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index 4e16e57058d..14b8c1d1127 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -299,19 +299,29 @@ select 'aaa\\','aa''a',"aa""a";
#
-# Check of include/show_msg.inc
+# Check of include/show_msg.inc and include/show_msg80.inc
#
# The message contains in most cases a string with the default character set
-SET @message = 'Here comes a message';
+let $message= Here comes a message;
--source include/show_msg.inc
# The message could also contain a string with character set utf8
-SET @message = USER();
+let $message= `SELECT USER()`;
--source include/show_msg.inc
# The message contains more then 80 characters on multiple lines
-SET @message = 'Here comes a very very long message that is longer then 80 characters
-on multiple lines';
+# and is kept between double quotes.
+let $message=
+"Here comes a very very long message that
+ - is longer then 80 characters and
+ - consists of several lines";
+--source include/show_msg80.inc
+
+# The message contains more then 80 characters on multiple lines
+# and uses the auxiliary character "." at the beginning of the message lines.
+let $message= . Here comes a very very long message that
+ . - is longer then 80 characters and
+ . - consists of several lines;
--source include/show_msg80.inc
diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test
index 80f6f3f35d3..079ebd09ae1 100644
--- a/mysql-test/t/ndb_autodiscover.test
+++ b/mysql-test/t/ndb_autodiscover.test
@@ -494,6 +494,27 @@ select * from t1;
use test;
drop database test_only_ndb_tables;
+#####################################################
+# Test that it's not possible to create tables
+# with same name as NDB internal tables
+# This will also test that it's not possible to create
+# a table with tha same name as a table that can't be
+# discovered( for example a table created via NDBAPI)
+
+--error 1050
+CREATE TABLE sys.SYSTAB_0 (a int);
+--error 1105
+select * from sys.SYSTAB_0;
+
+CREATE TABLE IF NOT EXISTS sys.SYSTAB_0 (a int);
+show warnings;
+--error 1105
+select * from sys.SYSTAB_0;
+
+--error 1051
+drop table sys.SYSTAB_0;
+drop table IF EXISTS sys.SYSTAB_0;
+
######################################################
# Note! This should always be the last step in this
# file, the table t9 will be used and dropped
diff --git a/mysql-test/t/ndb_insert.test b/mysql-test/t/ndb_insert.test
index f88d33f22f4..68f3817e134 100644
--- a/mysql-test/t/ndb_insert.test
+++ b/mysql-test/t/ndb_insert.test
@@ -434,6 +434,9 @@ SELECT COUNT(*) FROM t1;
# Insert duplicate rows
#
--error 1062
+INSERT INTO t1 VALUES (1,1,1);
+
+--error 1022
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
@@ -457,7 +460,7 @@ rollback;
#
begin;
---error 1062
+--error 1022
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
@@ -477,7 +480,7 @@ select count(*) from t1;
#
begin;
---error 1062
+--error 1022
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
@@ -496,7 +499,7 @@ select count(*) from t1;
#
begin;
---error 1062
+--error 1022
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
@@ -517,7 +520,7 @@ select count(*) from t1;
#
begin;
---error 1062
+--error 1022
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
@@ -543,7 +546,7 @@ select count(*) from t1;
#
begin;
---error 1062
+--error 1022
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
@@ -562,7 +565,7 @@ select count(*) from t1;
# Insert duplicate rows using "insert .. select"
#
---error 1062
+--error 1022
insert into t1 select * from t1 where b < 10 order by pk1;
DELETE FROM t1 WHERE pk1=2;
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 60b77576572..913b6c645af 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -149,7 +149,7 @@ create table t1
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
+ c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 bit, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -693,3 +693,15 @@ execute stmt using @offset, @limit, @offset, @limit, @limit;
drop table t1;
deallocate prepare stmt;
+
+#
+# Bug#11060 "Server crashes on calling stored procedure with INSERT SELECT
+# UNION SELECT" aka "Server crashes on re-execution of prepared INSERT ...
+# SELECT with UNION".
+#
+create table t1 (id int);
+prepare stmt from "insert into t1 (id) select id from t1 union select id from t1";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+drop table t1;
diff --git a/mysql-test/t/ps_4heap.test b/mysql-test/t/ps_4heap.test
index 1c9346721ab..3ce3bea8265 100644
--- a/mysql-test/t/ps_4heap.test
+++ b/mysql-test/t/ps_4heap.test
@@ -31,7 +31,7 @@ eval create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
+ c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100),
c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100),
diff --git a/mysql-test/t/ps_5merge.test b/mysql-test/t/ps_5merge.test
index 891d1be2c57..7e94ede41d1 100644
--- a/mysql-test/t/ps_5merge.test
+++ b/mysql-test/t/ps_5merge.test
@@ -31,7 +31,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
+ c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -62,7 +62,7 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
+ c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index d4e3b95e4a2..88891bd3881 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -756,4 +756,36 @@ flush query cache;
drop table t1, t2;
+#
+# SP cursors and selects with query cache (BUG#9715)
+#
+create table t1 (a int);
+insert into t1 values (1),(2);
+
+delimiter //;
+CREATE PROCEDURE `p1`()
+begin
+Declare c1 cursor for select a from t1;
+open c1;
+select * from t1;
+end//
+call p1()//
+drop procedure p1;
+
+create function f1() returns int
+begin
+Declare var1 int;
+select max(a) from t1 into var1;
+return var1;
+end//
+create procedure `p1`()
+begin
+ select a, f1() from t1;
+end//
+call p1()//
+drop procedure p1//
+
+drop table t1//
+delimiter ;//
+
set GLOBAL query_cache_size=0;
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index a5822602b82..3d2285b1633 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -418,6 +418,41 @@ select count(*) from t2 where x > -16;
select count(*) from t2 where x = 18446744073709551601;
drop table t1,t2;
+--disable_warnings
+create table t1 (x bigint unsigned not null primary key) engine=innodb;
+--enable_warnings
+insert into t1(x) values (0xfffffffffffffff0);
+insert into t1(x) values (0xfffffffffffffff1);
+select * from t1;
+select count(*) from t1 where x>0;
+select count(*) from t1 where x=0;
+select count(*) from t1 where x<0;
+select count(*) from t1 where x < -16;
+select count(*) from t1 where x = -16;
+select count(*) from t1 where x > -16;
+select count(*) from t1 where x = 18446744073709551601;
+
+drop table t1;
+
+#
+# Bug #11185 incorrect comparison of unsigned int to signed constant
+#
+create table t1 (a bigint unsigned);
+create index t1i on t1(a);
+insert into t1 select 18446744073709551615;
+insert into t1 select 18446744073709551614;
+
+explain select * from t1 where a <> -1;
+select * from t1 where a <> -1;
+explain select * from t1 where a > -1 or a < -1;
+select * from t1 where a > -1 or a < -1;
+explain select * from t1 where a > -1;
+select * from t1 where a > -1;
+explain select * from t1 where a < -1;
+select * from t1 where a < -1;
+
+drop table t1;
+
#
# Bug #6045: Binary Comparison regression in MySQL 4.1
# Binary searches didn't use a case insensitive index.
@@ -495,3 +530,26 @@ SELECT * FROM t1 WHERE status NOT BETWEEN 'A' AND 'B';
SELECT * FROM t1 WHERE status < 'A' OR status > 'B';
DROP TABLE t1;
+
+#
+# Test for bug #10031: range to be used over a view
+#
+
+CREATE TABLE t1 (a int, b int, primary key(a,b));
+
+INSERT INTO t1 VALUES
+ (1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3);
+
+CREATE VIEW v1 as SELECT a,b FROM t1 WHERE b=3;
+
+EXPLAIN SELECT a,b FROM t1 WHERE a < 2 and b=3;
+EXPLAIN SELECT a,b FROM v1 WHERE a < 2 and b=3;
+
+EXPLAIN SELECT a,b FROM t1 WHERE a < 2;
+EXPLAIN SELECT a,b FROM v1 WHERE a < 2;
+
+SELECT a,b FROM t1 WHERE a < 2 and b=3;
+SELECT a,b FROM v1 WHERE a < 2 and b=3;
+
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/t/rpl_ddl.test b/mysql-test/t/rpl_ddl.test
new file mode 100644
index 00000000000..d043d40d96e
--- /dev/null
+++ b/mysql-test/t/rpl_ddl.test
@@ -0,0 +1,350 @@
+######################## rpl_ddl.test ########################
+# #
+# DDL statements (sometimes with implicit COMMIT) executed #
+# by the master and it's propagation into the slave #
+# #
+##############################################################
+
+#
+# NOTE, PLEASE BE CAREFUL, WHEN MODIFYING THE TESTS !!
+#
+# 1. !All! objects to be dropped, renamed, altered ... must be created
+# in AUTOCOMMIT= 1 mode before AUTOCOMMIT is set to 0 and the test
+# sequences start.
+#
+# 2. Never use a test object, which was direct or indirect affected by a
+# preceeding test sequence again.
+# Except table d1.t1 where ONLY DML is allowed.
+#
+# If one preceeding test sequence hits a (sometimes not good visible,
+# because the sql error code of the statement might be 0) bug
+# and these rules are ignored, a following test sequence might earn ugly
+# effects like failing 'sync_slave_with_master', crashes of the slave or
+# abort of the test case etc..
+#
+# 3. The assignment of the DDL command to be tested to $my_stmt can
+# be a bit difficult. "'" must be avoided, because the test
+# routine "include/rpl_stmt_seq.inc" performs a
+# eval SELECT CONCAT('######## ','$my_stmt',' ########') as "";
+#
+
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+###############################################################
+# Some preparations
+###############################################################
+# The sync_slave_with_master is needed to make the xids deterministic.
+sync_slave_with_master;
+connection master;
+
+SET AUTOCOMMIT = 1;
+#
+# 1. DROP all objects, which probably already exist, but must be created here
+#
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+DROP DATABASE IF EXISTS mysqltest3;
+--enable_warnings
+#
+# 2. CREATE all objects needed
+# working database is mysqltest1
+# working (transactional!) is mysqltest1.t1
+#
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE TABLE mysqltest1.t1 (f1 BIGINT) ENGINE= "InnoDB";
+INSERT INTO mysqltest1.t1 SET f1= 0;
+CREATE TABLE mysqltest1.t2 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t3 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t4 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t5 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t6 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE INDEX my_idx6 ON mysqltest1.t6(f1);
+CREATE TABLE mysqltest1.t7 (f1 BIGINT) ENGINE= "InnoDB";
+INSERT INTO mysqltest1.t7 SET f1= 0;
+CREATE TABLE mysqltest1.t8 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t9 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t10 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t11 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t12 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t13 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t14 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t15 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t16 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t17 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t18 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TABLE mysqltest1.t19 (f1 BIGINT) ENGINE= "InnoDB";
+CREATE TEMPORARY TABLE mysqltest1.t23 (f1 BIGINT);
+
+#
+# 3. master sessions: never do AUTOCOMMIT
+# slave sessions: never do AUTOCOMMIT
+#
+SET AUTOCOMMIT = 0;
+use mysqltest1;
+sync_slave_with_master;
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+SET AUTOCOMMIT = 0;
+use mysqltest1;
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+
+# We don't want to abort the whole test if one statement sent
+# to the server gets an error, because the following test
+# sequences are nearly independend of the previous statements.
+--disable_abort_on_error
+
+###############################################################
+# Banal case: (explicit) COMMIT and ROLLBACK
+# Just for checking if the test sequence is usable
+###############################################################
+
+let $my_stmt= COMMIT;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+
+let $my_stmt= ROLLBACK;
+let $my_master_commit= false;
+let $my_slave_commit= false;
+--source include/rpl_stmt_seq.inc
+
+###############################################################
+# Cases with commands very similar to COMMIT
+###############################################################
+
+let $my_stmt= SET AUTOCOMMIT=1;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+SET AUTOCOMMIT=0;
+
+let $my_stmt= START TRANSACTION;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+
+let $my_stmt= BEGIN;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+
+###############################################################
+# Cases with (BASE) TABLES and (UPDATABLE) VIEWs
+###############################################################
+
+let $my_stmt= DROP TABLE mysqltest1.t2;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+SHOW TABLES LIKE 't2';
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+SHOW TABLES LIKE 't2';
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+# Note: Since this test is executed with a skip-innodb slave, the
+# slave incorrectly commits the insert. One can *not* have InnoDB on
+# master and MyISAM on slave and expect that a transactional rollback
+# after a CREATE TEMPORARY TABLE should work correctly on the slave.
+# For this to work properly the handler on the slave must be able to
+# handle transactions (e.g. InnoDB or NDB).
+let $my_stmt= DROP TEMPORARY TABLE mysqltest1.t23;
+let $my_master_commit= false;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+SHOW TABLES LIKE 't23';
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+SHOW TABLES LIKE 't23';
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+let $my_stmt= RENAME TABLE mysqltest1.t3 to mysqltest1.t20;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+SHOW TABLES LIKE 't20';
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+SHOW TABLES LIKE 't20';
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+let $my_stmt= ALTER TABLE mysqltest1.t4 ADD column f2 BIGINT;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+describe mysqltest1.t4;
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+describe mysqltest1.t4;
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+let $my_stmt= CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE= "InnoDB";
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+
+# Note: Since this test is executed with a skip-innodb slave, the
+# slave incorrectly commits the insert. One can *not* have InnoDB on
+# master and MyISAM on slave and expect that a transactional rollback
+# after a CREATE TEMPORARY TABLE should work correctly on the slave.
+# For this to work properly the handler on the slave must be able to
+# handle transactions (e.g. InnoDB or NDB).
+let $my_stmt= CREATE TEMPORARY TABLE mysqltest1.t22 (f1 BIGINT);
+let $my_master_commit= false;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+
+let $my_stmt= TRUNCATE TABLE mysqltest1.t7;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+SELECT * FROM mysqltest1.t7;
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+SELECT * FROM mysqltest1.t7;
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+###############################################################
+# Cases with LOCK/UNLOCK
+###############################################################
+
+# MySQL insists in locking mysqltest1.t1, because rpl_stmt_seq performs an
+# INSERT into this table.
+let $my_stmt= LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+UNLOCK TABLES;
+
+# No prior locking
+let $my_stmt= UNLOCK TABLES;
+let $my_master_commit= false;
+let $my_slave_commit= false;
+--source include/rpl_stmt_seq.inc
+
+# With prior read locking
+# Note that this test generate an error since the rpl_stmt_seq.inc
+# tries to insert into t1.
+LOCK TABLES mysqltest1.t1 READ;
+let $my_stmt= UNLOCK TABLES;
+let $my_master_commit= false;
+let $my_slave_commit= false;
+--source include/rpl_stmt_seq.inc
+
+# With prior write locking
+LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ;
+let $my_stmt= UNLOCK TABLES;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+
+###############################################################
+# Cases with INDEXES
+###############################################################
+
+let $my_stmt= DROP INDEX my_idx6 ON mysqltest1.t6;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+SHOW INDEX FROM mysqltest1.t6;
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+SHOW INDEX FROM mysqltest1.t6;
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+let $my_stmt= CREATE INDEX my_idx5 ON mysqltest1.t5(f1);
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+SHOW INDEX FROM mysqltest1.t5;
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+SHOW INDEX FROM mysqltest1.t5;
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+###############################################################
+# Cases with DATABASE
+###############################################################
+
+let $my_stmt= DROP DATABASE mysqltest2;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+SHOW DATABASES LIKE "mysqltest2";
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+SHOW DATABASES LIKE "mysqltest2";
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+let $my_stmt= CREATE DATABASE mysqltest3;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+SHOW DATABASES LIKE "mysqltest3";
+connection slave;
+--disable_query_log
+SELECT '-------- switch to slave --------' as "";
+--enable_query_log
+SHOW DATABASES LIKE "mysqltest3";
+connection master;
+--disable_query_log
+SELECT '-------- switch to master -------' as "";
+--enable_query_log
+
+###############################################################
+# Cleanup
+###############################################################
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+DROP DATABASE IF EXISTS mysqltest3;
+--enable_warnings
diff --git a/mysql-test/t/rpl_multi_update3.test b/mysql-test/t/rpl_multi_update3.test
new file mode 100644
index 00000000000..80b0603eb60
--- /dev/null
+++ b/mysql-test/t/rpl_multi_update3.test
@@ -0,0 +1,159 @@
+source include/master-slave.inc;
+
+##############################################################################
+#
+# Let's verify that multi-update with a subselect does not cause the slave to crash
+# (BUG#10442)
+#
+--disable_query_log
+SELECT '-------- Test for BUG#9361 --------' as "";
+--enable_query_log
+
+CREATE TABLE t1 (
+ a int unsigned not null auto_increment primary key,
+ b int unsigned
+) ENGINE=MyISAM;
+
+CREATE TABLE t2 (
+ a int unsigned not null auto_increment primary key,
+ b int unsigned
+) ENGINE=MyISAM;
+
+INSERT INTO t1 VALUES (NULL, 0);
+INSERT INTO t1 SELECT NULL, 0 FROM t1;
+
+INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+UPDATE t2, (SELECT a FROM t1) AS t SET t2.b = t.a+5 ;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+connection master;
+drop table t1,t2;
+
+##############################################################################
+#
+# Test for BUG#9361:
+# Subselects should work inside multi-updates
+#
+--disable_query_log
+SELECT '-------- Test 1 for BUG#9361 --------' as "";
+--enable_query_log
+
+connection master;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+
+CREATE TABLE t1 (
+ a1 char(30),
+ a2 int,
+ a3 int,
+ a4 char(30),
+ a5 char(30)
+);
+
+CREATE TABLE t2 (
+ b1 int,
+ b2 char(30)
+);
+
+# Insert one row per table
+INSERT INTO t1 VALUES ('Yes', 1, NULL, 'foo', 'bar');
+INSERT INTO t2 VALUES (1, 'baz');
+
+# This should update the row in t1
+UPDATE t1 a, t2
+ SET a.a1 = 'No'
+ WHERE a.a2 =
+ (SELECT b1
+ FROM t2
+ WHERE b2 = 'baz')
+ AND a.a3 IS NULL
+ AND a.a4 = 'foo'
+ AND a.a5 = 'bar';
+
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+connection master;
+DROP TABLE t1, t2;
+
+##############################################################################
+#
+# Second test for BUG#9361
+#
+
+--disable_query_log
+SELECT '-------- Test 2 for BUG#9361 --------' as "";
+--enable_query_log
+
+connection master;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+--enable_warnings
+
+CREATE TABLE t1 (
+ i INT,
+ j INT,
+ x INT,
+ y INT,
+ z INT
+);
+
+CREATE TABLE t2 (
+ i INT,
+ k INT,
+ x INT,
+ y INT,
+ z INT
+);
+
+CREATE TABLE t3 (
+ j INT,
+ k INT,
+ x INT,
+ y INT,
+ z INT
+);
+
+INSERT INTO t1 VALUES ( 1, 2,13,14,15);
+INSERT INTO t2 VALUES ( 1, 3,23,24,25);
+INSERT INTO t3 VALUES ( 2, 3, 1,34,35), ( 2, 3, 1,34,36);
+
+UPDATE t1 AS a
+INNER JOIN t2 AS b
+ ON a.i = b.i
+INNER JOIN t3 AS c
+ ON a.j = c.j AND b.k = c.k
+SET a.x = b.x,
+ a.y = b.y,
+ a.z = (
+ SELECT sum(z)
+ FROM t3
+ WHERE y = 34
+ )
+WHERE b.x = 23;
+
+sync_slave_with_master;
+connection slave;
+
+SELECT * FROM t1;
+
+connection master;
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 372325c4cbd..e131c3d0517 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -1789,7 +1789,7 @@ DROP TABLE t1;
# Test of bug with SUM(CASE...)
#
-CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp(14) NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
+CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (200001,2,1,1,100,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\E$',''),(200002,2,2,1,101,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\C$',''),(200003,1,3,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,20020425060427,'c:',NULL);
CREATE TABLE t2 ( hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, sampletid smallint(5) unsigned default NULL, sampletime datetime default NULL, samplevalue bigint(20) unsigned default NULL, KEY idx1 (hmid,volid,sampletid,sampletime)) ENGINE=MyISAM;
INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12:00:01',35);
@@ -2271,3 +2271,8 @@ EXPLAIN SELECT t1.a FROM t1 INNER JOIN t2 ON t1.a=t2.a;
DROP TABLE t1,t2;
+#
+# Bug #10650
+#
+
+select x'10' + 0, X'10' + 0, b'10' + 0, B'10' + 0;
diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test
index e1d8043ccda..72fe6c332bf 100644
--- a/mysql-test/t/sp-security.test
+++ b/mysql-test/t/sp-security.test
@@ -304,3 +304,39 @@ drop database sptest;
delete from mysql.user where user='usera' or user='userb' or user='userc';
delete from mysql.procs_priv where user='usera' or user='userb' or user='userc';
+#
+# BUG#9503: reseting correct parameters of thread after error in SP function
+#
+connect (root,localhost,root,,test);
+connection root;
+
+--disable_warnings
+drop function if exists bug_9503;
+--enable_warnings
+delimiter //;
+create database mysqltest//
+use mysqltest//
+create table t1 (s1 int)//
+grant select on t1 to user1@localhost//
+create function bug_9503 () returns int sql security invoker begin declare v int;
+select min(s1) into v from t1; return v; end//
+delimiter ;//
+
+connect (user1,localhost,user1,,test);
+connection user1;
+use mysqltest;
+-- error 1370
+select bug_9503();
+
+connection root;
+grant execute on function bug_9503 to user1@localhost;
+
+connection user1;
+do 1;
+use test;
+
+connection root;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost;
+drop function bug_9503;
+use test;
+drop database mysqltest;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 20b1a98702c..e7ee4b134ba 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -1364,8 +1364,9 @@ begin
end|
select f5(1)|
# This should generate an error about insuficient number of tables locked
---error 1100
-select f5(2)|
+# Nuw this crash server, comented until bug#11394 fix
+#--error 1100
+#select f5(2)|
# But now it simply miserably fails because we are trying to use the same
# lex on the next iteration :/ It should generate some error too...
# select f5(3)|
@@ -3887,6 +3888,30 @@ DROP VIEW tv|
DROP TABLE tt1, tt2, tt3|
#
+# BUG#10136: items cleunup
+#
+--disable_warnings
+DROP PROCEDURE IF EXISTS bug10136|
+--enable_warnings
+create table t3 ( name char(5) not null primary key, val float not null)|
+insert into t3 values ('aaaaa', 1), ('bbbbb', 2), ('ccccc', 3)|
+create procedure bug10136()
+begin
+ declare done int default 3;
+
+ repeat
+ select * from t3;
+ set done = done - 1;
+ until done <= 0 end repeat;
+
+end|
+call bug10136()|
+call bug10136()|
+call bug10136()|
+drop procedure bug10136|
+drop table t3|
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test
index d860d4818ba..82e1cd2f1c9 100644
--- a/mysql-test/t/sp_trans.test
+++ b/mysql-test/t/sp_trans.test
@@ -24,14 +24,10 @@ end|
set autocommit=0|
insert t1 values (2)|
---error 1192
call bug8850()|
commit|
select * from t1|
-#
-# when CALL will be fixed to not start a transaction, the error should
-# go away
---error 1192
+
call bug8850()|
set autocommit=1|
select * from t1|
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
index 6a0c4aecada..26cb0944e3a 100644
--- a/mysql-test/t/sql_mode.test
+++ b/mysql-test/t/sql_mode.test
@@ -189,4 +189,24 @@ SET @@SQL_MODE='';
SELECT 'a\\b', 'a\\\"b', 'a''\\b', 'a''\\\"b';
SELECT "a\\b", "a\\\'b", "a""\\b", "a""\\\'b";
+
+#
+# Bug#6877: MySQL should give an error if the requested table type
+# is not available
+#
+
+set session sql_mode = 'NO_ENGINE_SUBSTITUTION';
+--error 1289
+create table t1 (a int) engine=isam;
+--error 1146
+show create table t1;
+drop table if exists t1;
+
+# for comparison, lets see the warnings...
+set session sql_mode = '';
+create table t1 (a int) engine=isam;
+show create table t1;
+drop table t1;
+
+
SET @@SQL_MODE=@OLD_SQL_MODE;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 2e6cea8468b..1e4930d385d 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1837,3 +1837,25 @@ WHERE t1.EMPNUM NOT IN
WHERE t1.EMPNUM = t2.EMPNUM);
select * from t1;
DROP TABLE t1,t2;
+
+#
+# Test for bug #11487: range access in a subquery
+#
+
+CREATE TABLE t1(select_id BIGINT, values_id BIGINT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TABLE t2 (select_id BIGINT, values_id BIGINT,
+ PRIMARY KEY(select_id,values_id));
+INSERT INTO t2 VALUES (0, 1), (0, 2), (0, 3), (1, 5);
+
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+ WHERE select_id IN (1, 0));
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+ WHERE select_id BETWEEN 0 AND 1);
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+ WHERE select_id = 0 OR select_id = 1);
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 0c5ef077159..05241772693 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -494,3 +494,17 @@ replace into t1 (i, k) values (2, 11);
select * from t1;
# Also drops all triggers
drop table t1, t2;
+
+# Test for bug #5893 "Triggers with dropped functions cause crashes"
+# Appropriate error should be reported instead of crash.
+--disable_warnings
+drop function if exists bug5893;
+--enable_warnings
+create table t1 (col1 int, col2 int);
+insert into t1 values (1, 2);
+create function bug5893 () returns int return 5;
+create trigger t1_bu before update on t1 for each row set new.col1= bug5893();
+drop function bug5893;
+--error 1305
+update t1 set col2 = 4;
+drop table t1;
diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test
index 2df5f0ed05d..fd5eb49858c 100644
--- a/mysql-test/t/type_bit.test
+++ b/mysql-test/t/type_bit.test
@@ -171,3 +171,56 @@ create table t1 (a bit(8)) engine=heap;
insert into t1 values ('1111100000');
select a+0 from t1;
drop table t1;
+
+#
+# Bug #11091: union
+#
+
+create table t1 (a bit(7));
+insert into t1 values (120), (0), (111);
+select a+0 from t1 union select a+0 from t1;
+select a+0 from t1 union select NULL;
+select NULL union select a+0 from t1;
+create table t2 select a from t1 union select a from t1;
+select a+0 from t2;
+show create table t2;
+drop table t1, t2;
+
+#
+# Bug #11572: view
+#
+
+create table t1 (id1 int(11), b1 bit(1));
+create table t2 (id2 int(11), b2 bit(1));
+insert into t1 values (1, 1), (2, 0), (3, 1);
+insert into t2 values (2, 1), (3, 0), (4, 0);
+create algorithm=undefined view v1 as
+ select b1+0, b2+0 from t1, t2 where id1 = id2 and b1 = 0
+ union
+ select b1+0, b2+0 from t1, t2 where id1 = id2 and b2 = 1;
+select * from v1;
+drop table t1, t2;
+drop view v1;
+
+#
+# Bug #10617: bulk-insert
+#
+
+create table t1(a bit(4));
+insert into t1(a) values (1), (2), (5), (4), (3);
+insert into t1 select * from t1;
+select a+0 from t1;
+drop table t1;
+
+#
+# join
+#
+
+create table t1 (a1 int(11), b1 bit(2));
+create table t2 (a2 int(11), b2 bit(2));
+insert into t1 values (1, 1), (2, 0), (3, 1), (4, 2);
+insert into t2 values (2, 1), (3, 0), (4, 1), (5, 2);
+select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2;
+select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2 order by a1;
+select a1, a2, b1+0, b2+0 from t1 join t2 on b1 = b2;
+select sum(a1), b1+0, b2+0 from t1 join t2 on b1 = b2 group by b1 order by 1;
diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
index 6199bd34fa9..5c4f288983b 100644
--- a/mysql-test/t/type_newdecimal.test
+++ b/mysql-test/t/type_newdecimal.test
@@ -964,3 +964,12 @@ insert into t1 values (0.00);
select * from t1 where a > -0.00;
select * from t1 where a = -0.00;
drop table t1;
+
+#
+# Bug #11215: a problem with LONGLONG_MIN
+#
+
+create table t1 (col1 bigint default -9223372036854775808);
+insert into t1 values (default);
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index 6a90fb95760..21789a550b9 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -31,7 +31,7 @@ CREATE TABLE t1
clicks int(10) unsigned DEFAULT '0' NOT NULL,
iclicks int(10) unsigned DEFAULT '0' NOT NULL,
uclicks int(10) unsigned DEFAULT '0' NOT NULL,
- ts timestamp(14),
+ ts timestamp,
PRIMARY KEY (place_id,ts)
);
@@ -52,7 +52,7 @@ CREATE TABLE t1 (
replyto varchar(255) NOT NULL default '',
subject varchar(100) NOT NULL default '',
timestamp int(10) unsigned NOT NULL default '0',
- tstamp timestamp(14) NOT NULL,
+ tstamp timestamp NOT NULL,
status int(3) NOT NULL default '0',
type varchar(15) NOT NULL default '',
assignment int(10) unsigned NOT NULL default '0',
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 0477ab0ea20..06b523b3610 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -1569,3 +1569,130 @@ drop procedure p1;
drop view v1;
drop table t1;
+#
+# Bug#7422 "order by" doesn't work
+#
+CREATE TABLE t1(a char(2) primary key, b char(2));
+CREATE TABLE t2(a char(2), b char(2), index i(a));
+INSERT INTO t1 VALUES ('a','1'), ('b','2');
+INSERT INTO t2 VALUES ('a','5'), ('a','6'), ('b','5'), ('b','6');
+CREATE VIEW v1 AS
+ SELECT t1.b as c, t2.b as d FROM t1,t2 WHERE t1.a=t2.a;
+SELECT d, c FROM v1 ORDER BY d,c;
+DROP VIEW v1;
+DROP TABLE t1, t2;
+#
+# using sum(distinct ) & avg(distinct ) in views (BUG#7015)
+#
+create table t1 (s1 int);
+create view v1 as select sum(distinct s1) from t1;
+select * from v1;
+drop view v1;
+create view v1 as select avg(distinct s1) from t1;
+select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# using cast(... as decimal) in views (BUG#11387);
+#
+create view v1 as select cast(1 as decimal);
+select * from v1;
+drop view v1;
+
+#
+# Bug#11298 insert into select from VIEW produces incorrect result when
+# using ORDER BY
+create table t1(f1 int);
+create table t2(f2 int);
+insert into t1 values(1),(2),(3);
+insert into t2 values(1),(2),(3);
+create view v1 as select * from t1,t2 where f1=f2;
+create table t3 (f1 int, f2 int);
+insert into t3 select * from v1 order by 1;
+select * from t3;
+drop view v1;
+drop table t1,t2,t3;
+
+#
+# Generation unique names for columns, and correct names check (BUG#7448)
+#
+# names with ' and \
+create view v1 as select '\\','\\shazam';
+select * from v1;
+drop view v1;
+create view v1 as select '\'','\shazam';
+select * from v1;
+drop view v1;
+# autogenerated names differ by case only
+create view v1 as select 'k','K';
+select * from v1;
+drop view v1;
+create table t1 (s1 int);
+# same autogenerated names
+create view v1 as select s1, 's1' from t1;
+select * from v1;
+drop view v1;
+create view v1 as select 's1', s1 from t1;
+select * from v1;
+drop view v1;
+# set name as one of expected autogenerated
+create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
+select * from v1;
+drop view v1;
+create view v1 as select 1 as My_exp_s1, 's1', s1 from t1;
+select * from v1;
+drop view v1;
+# set name conflict with autogenerated names
+create view v1 as select 1 as s1, 's1', 's1' from t1;
+select * from v1;
+drop view v1;
+create view v1 as select 's1', 's1', 1 as s1 from t1;
+select * from v1;
+drop view v1;
+# underlying field name conflict with autogenerated names
+create view v1 as select s1, 's1', 's1' from t1;
+select * from v1;
+drop view v1;
+create view v1 as select 's1', 's1', s1 from t1;
+select * from v1;
+drop view v1;
+# underlying field name conflict with set name
+-- error 1060
+create view v1 as select 1 as s1, 's1', s1 from t1;
+-- error 1060
+create view v1 as select 's1', s1, 1 as s1 from t1;
+drop table t1;
+# set names differ by case only
+-- error 1060
+create view v1(k, K) as select 1,2;
+
+#
+# using time_format in view (BUG#7521)
+#
+create view v1 as SELECT TIME_FORMAT(SEC_TO_TIME(3600),'%H:%i') as t;
+select * from v1;
+drop view v1;
+
+#
+# bug #11325 Wrong date comparison in views
+#
+create table t1 (f1 date);
+insert into t1 values ('2005-01-01'),('2005-02-02');
+create view v1 as select * from t1;
+select * from v1 where f1='2005.02.02';
+select * from v1 where '2005.02.02'=f1;
+drop view v1;
+drop table t1;
+
+#
+# using encrypt & substring_index in view (BUG#7024)
+#
+CREATE VIEW v1 AS SELECT ENCRYPT("dhgdhgd");
+disable_result_log;
+SELECT * FROM v1;
+enable_result_log;
+drop view v1;
+CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1);
+SELECT * FROM v1;
+drop view v1;
diff --git a/mysys/charset.c b/mysys/charset.c
index 534a6aa998e..cbd9ba16b4c 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -97,7 +97,7 @@ static my_bool init_state_maps(CHARSET_INFO *cs)
/* Special handling of hex and binary strings */
state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) MY_LEX_IDENT_OR_HEX;
- state_map[(uchar)'b']= state_map[(uchar)'b']= (uchar) MY_LEX_IDENT_OR_BIN;
+ state_map[(uchar)'b']= state_map[(uchar)'B']= (uchar) MY_LEX_IDENT_OR_BIN;
state_map[(uchar)'n']= state_map[(uchar)'N']= (uchar) MY_LEX_IDENT_OR_NCHAR;
return 0;
}
diff --git a/mysys/default.c b/mysys/default.c
index 45b27806dc4..1fa8deaa65c 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -914,7 +914,7 @@ static void init_default_directories()
/* Only add shared system directory if different from default. */
if (GetSystemWindowsDirectory(shared_system_dir,sizeof(shared_system_dir)) &&
strcmp(system_dir, shared_system_dir))
- *ptr++= &shared_system_dir;
+ *ptr++= (char *)&shared_system_dir;
#endif
#elif defined(__NETWARE__)
diff --git a/mysys/default_modify.c b/mysys/default_modify.c
index 721ca596428..ea384f9f27a 100644
--- a/mysys/default_modify.c
+++ b/mysys/default_modify.c
@@ -1,3 +1,40 @@
+/* Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; 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 "my_global.h"
+#include "mysys_priv.h"
+#include "m_string.h"
+#include <my_dir.h>
+
+#define BUFF_SIZE 1024
+/* should be big enough to handle at least one line */
+#define RESERVE 1024
+
+#ifdef __WIN__
+#define NEWLINE "\r\n"
+#define NEWLINE_LEN 2
+#else
+#define NEWLINE "\n"
+#define NEWLINE_LEN 1
+#endif
+
+static char *add_option(char *dst, const char *option_value,
+ const char *option, int remove_option);
+
+
/*
Add/remove option to the option file section.
@@ -15,6 +52,8 @@
into a buffer. Then we look for the option within this section and
change/remove it. In the end we get a buffer with modified version of the
file. Then we write it to the file, truncate it if needed and close it.
+ Note that there is a small time gap, when the file is incomplete,
+ and this theoretically might introduce a problem.
RETURN
0 - ok
@@ -22,24 +61,6 @@
2 - cannot open the file
*/
-#include "my_global.h"
-#include "mysys_priv.h"
-#include "m_string.h"
-#include <my_dir.h>
-
-#define BUFF_SIZE 1024
-
-#ifdef __WIN__
-#define NEWLINE "\r\n"
-#define NEWLINE_LEN 2
-#else
-#define NEWLINE "\n"
-#define NEWLINE_LEN 1
-#endif
-
-static char *add_option(char *dst, const char *option_value,
- const char *option, int remove_option);
-
int modify_defaults_file(const char *file_location, const char *option,
const char *option_value,
const char *section_name, int remove_option)
@@ -47,8 +68,11 @@ int modify_defaults_file(const char *file_location, const char *option,
FILE *cnf_file;
MY_STAT file_stat;
char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer;
- uint optlen, optval_len, sect_len, nr_newlines= 0;
+ uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size;
my_bool in_section= FALSE, opt_applied= 0;
+ uint reserve_extended= 1, old_opt_len= 0;
+ uint new_opt_len;
+ int reserve_occupied= 0;
DBUG_ENTER("modify_defaults_file");
if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0))))
@@ -56,30 +80,36 @@ int modify_defaults_file(const char *file_location, const char *option,
/* my_fstat doesn't use the flag parameter */
if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
- goto err;
+ goto malloc_err;
- optlen= strlen(option);
- optval_len= strlen(option_value);
+ opt_len= (uint) strlen(option);
+ optval_len= (uint) strlen(option_value);
+
+ new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN;
+
+ /* calculate the size of the buffer we need */
+ buffer_size= sizeof(char) * (file_stat.st_size +
+ /* option name len */
+ opt_len +
+ /* reserve for '=' char */
+ 1 +
+ /* option value len */
+ optval_len +
+ /* reserve space for newline */
+ NEWLINE_LEN +
+ /* The ending zero */
+ 1 +
+ /* reserve some additional space */
+ RESERVE);
/*
Reserve space to read the contents of the file and some more
for the option we want to add.
*/
- if (!(file_buffer= (char*) my_malloc(sizeof(char) *
- (file_stat.st_size +
- /* option name len */
- optlen +
- /* reserve space for newline */
- NEWLINE_LEN +
- /* reserve for '=' char */
- 1 +
- /* option value len */
- optval_len +
- /* The ending zero plus some safety */
- FN_REFLEN), MYF(MY_WME))))
+ if (!(file_buffer= (char*) my_malloc(buffer_size, MYF(MY_WME))))
goto malloc_err;
- sect_len= strlen(section_name);
+ sect_len= (uint) strlen(section_name);
for (dst_ptr= file_buffer; fgets(linebuff, BUFF_SIZE, cnf_file); )
{
@@ -94,24 +124,50 @@ int modify_defaults_file(const char *file_location, const char *option,
continue;
}
- if (!opt_applied && in_section && !strncmp(src_ptr, option, optlen) &&
- (*(src_ptr + optlen) == '=' ||
- my_isspace(&my_charset_latin1, *(src_ptr + optlen)) ||
- *(src_ptr + optlen) == '\0'))
+ /* correct the option */
+ if (in_section && !strncmp(src_ptr, option, opt_len) &&
+ (*(src_ptr + opt_len) == '=' ||
+ my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) ||
+ *(src_ptr + opt_len) == '\0'))
{
+ /*
+ we should change all options. If opt_applied is set, we are running
+ into reserved memory area. Hence we should check for overruns.
+ */
+ if (opt_applied)
+ {
+ src_ptr+= opt_len; /* If we correct an option, we know it's name */
+ old_opt_len= opt_len;
+
+ while (*src_ptr++) /* Find the end of the line */
+ old_opt_len++;
+
+ /* could be negative */
+ reserve_occupied+= (int) new_opt_len - (int) old_opt_len;
+ if ((int) reserve_occupied > (int) (RESERVE*reserve_extended))
+ {
+ if (!(file_buffer= (char*) my_realloc(file_buffer, buffer_size +
+ RESERVE*reserve_extended,
+ MYF(MY_WME|MY_FREE_ON_ERROR))))
+ goto malloc_err;
+ reserve_extended++;
+ }
+ }
+ else
+ opt_applied= 1;
dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
- opt_applied= 1;
}
else
{
/* If going to new group and we have option to apply, do it now */
if (in_section && !opt_applied && *src_ptr == '[')
{
- dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
-
+ dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
+ opt_applied= 1; /* set the flag to do write() later */
}
+
for (; nr_newlines; nr_newlines--)
- dst_ptr= strmov(dst_ptr, NEWLINE);
+ dst_ptr= strmov(dst_ptr, NEWLINE);
dst_ptr= strmov(dst_ptr, linebuff);
}
/* Look for a section */
@@ -120,13 +176,13 @@ int modify_defaults_file(const char *file_location, const char *option,
/* Copy the line to the buffer */
if (!strncmp(++src_ptr, section_name, sect_len))
{
- src_ptr+= sect_len;
- /* Skip over whitespaces. They are allowed after section name */
- for (; my_isspace(&my_charset_latin1, *src_ptr); src_ptr++)
- {}
+ src_ptr+= sect_len;
+ /* Skip over whitespaces. They are allowed after section name */
+ for (; my_isspace(&my_charset_latin1, *src_ptr); src_ptr++)
+ {}
- if (*src_ptr != ']')
- continue; /* Missing closing parenthesis. Assume this was no group */
+ if (*src_ptr != ']')
+ continue; /* Missing closing parenthesis. Assume this was no group */
in_section= TRUE;
}
else
@@ -149,10 +205,10 @@ int modify_defaults_file(const char *file_location, const char *option,
{
/* Don't write the file if there are no changes to be made */
if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
- MYF(MY_WME)) ||
- my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
- my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer),
- MYF(MY_NABP)))
+ MYF(MY_WME)) ||
+ my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
+ my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer),
+ MYF(MY_NABP)))
goto err;
}
if (my_fclose(cnf_file, MYF(MY_WME)))
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index a55a2d81c2c..b000af19aa0 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -601,7 +601,7 @@ int _my_b_read_r(register IO_CACHE *info, byte *Buffer, uint Count)
info->error= info->share->active->error;
info->read_end= info->share->active->read_end;
info->pos_in_file= info->share->active->pos_in_file;
- len= (info->error == -1 ? -1 : info->read_end-info->buffer);
+ len= (int) (info->error == -1 ? -1 : info->read_end-info->buffer);
}
info->read_pos=info->buffer;
info->seek_not_done=0;
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index feb9c77a5b9..cb2e0c98e8a 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -2191,7 +2191,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
{
int error;
int last_errno= 0;
- uint count= end-cache;
+ uint count= (uint) (end-cache);
/* Don't lock the cache during the flush */
keycache_pthread_mutex_unlock(&keycache->cache_lock);
diff --git a/mysys/my_access.c b/mysys/my_access.c
index 28210bdfc7d..c01031827c0 100644
--- a/mysys/my_access.c
+++ b/mysys/my_access.c
@@ -93,18 +93,20 @@ int check_if_legal_filename(const char *path)
path+= dirname_length(path); /* To start of filename */
if (!(end= strchr(path, FN_EXTCHAR)))
end= strend(path);
- if (path == end || (uint) (path - end) > MAX_RESERVED_NAME_LENGTH)
+ if (path == end || (uint) (end - path) > MAX_RESERVED_NAME_LENGTH)
DBUG_RETURN(0); /* Simplify inner loop */
for (reserved_name= reserved_names; *reserved_name; reserved_name++)
{
const char *name= path;
- while (name != end)
+ const char *current_reserved_name= *reserved_name;
+
+ while (name != end && *current_reserved_name)
{
- if (my_toupper(&my_charset_latin1, *path) !=
- my_toupper(&my_charset_latin1, *name))
+ if (*current_reserved_name != my_toupper(&my_charset_latin1, *name))
break;
- if (name++ == end)
+ current_reserved_name++;
+ if (++name == end)
DBUG_RETURN(1); /* Found wrong path */
}
}
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index 4aa31829c59..619d6bd5654 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -333,7 +333,7 @@ void set_prealloc_root(MEM_ROOT *root, char *ptr)
char *strdup_root(MEM_ROOT *root,const char *str)
{
- return strmake_root(root, str, strlen(str));
+ return strmake_root(root, str, (uint) strlen(str));
}
char *strmake_root(MEM_ROOT *root,const char *str, uint len)
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 5e93ad56cb5..68bf65b2abe 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -180,7 +180,7 @@ int handle_options(int *argc, char ***argv,
}
opt_str= check_struct_option(cur_arg, key_name);
optend= strcend(opt_str, '=');
- length= optend - opt_str;
+ length= (uint) (optend - opt_str);
if (*optend == '=')
optend++;
else
@@ -323,7 +323,7 @@ int handle_options(int *argc, char ***argv,
return EXIT_NO_ARGUMENT_ALLOWED;
}
value= optp->var_type & GET_ASK_ADDR ?
- (*getopt_get_addr)(key_name, strlen(key_name), optp) : optp->value;
+ (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp) : optp->value;
if (optp->arg_type == NO_ARG)
{
@@ -519,7 +519,7 @@ static char *check_struct_option(char *cur_arg, char *key_name)
*/
if (end - ptr > 1)
{
- uint len= ptr - cur_arg;
+ uint len= (uint) (ptr - cur_arg);
set_if_smaller(len, FN_REFLEN-1);
strmake(key_name, cur_arg, len);
return ++ptr;
@@ -833,7 +833,7 @@ void my_print_help(const struct my_option *options)
if (strlen(optp->name))
{
printf("--%s", optp->name);
- col+= 2 + strlen(optp->name);
+ col+= 2 + (uint) strlen(optp->name);
if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
(optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
{
@@ -904,7 +904,7 @@ void my_print_variables(const struct my_option *options)
if (value)
{
printf("%s", optp->name);
- length= strlen(optp->name);
+ length= (uint) strlen(optp->name);
for (; length < name_space; length++)
putchar(' ');
switch ((optp->var_type & GET_TYPE_MASK)) {
diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c
index cd84630a761..21bfddae46c 100644
--- a/mysys/my_mmap.c
+++ b/mysys/my_mmap.c
@@ -53,7 +53,7 @@ void *my_mmap(void *addr, size_t len, int prot,
flProtect|=SEC_COMMIT;
hFileMap=CreateFileMapping(hFile, &mmap_security_attributes,
- PAGE_READWRITE, 0, len, NULL);
+ PAGE_READWRITE, 0, (DWORD) len, NULL);
if (hFileMap == 0)
return MAP_FAILED;
diff --git a/mysys/my_once.c b/mysys/my_once.c
index a4201810b03..ab5fcc51c0e 100644
--- a/mysys/my_once.c
+++ b/mysys/my_once.c
@@ -81,7 +81,7 @@ gptr my_once_alloc(unsigned int Size, myf MyFlags)
char *my_once_strdup(const char *src,myf myflags)
{
- uint len=strlen(src)+1;
+ uint len= (uint) strlen(src)+1;
char *dst=my_once_alloc(len, myflags);
if (dst)
memcpy(dst, src, len);
diff --git a/mysys/string.c b/mysys/string.c
index ea747bc9847..dfd42d137dd 100644
--- a/mysys/string.c
+++ b/mysys/string.c
@@ -91,7 +91,7 @@ my_bool dynstr_realloc(DYNAMIC_STRING *str, ulong additional_size)
my_bool dynstr_append(DYNAMIC_STRING *str, const char *append)
{
- return dynstr_append_mem(str,append,strlen(append));
+ return dynstr_append_mem(str,append,(uint) strlen(append));
}
diff --git a/mysys/tree.c b/mysys/tree.c
index bec1ec680f1..1780913961e 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -263,6 +263,9 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
if (tree->flag & TREE_NO_DUPS)
return(NULL);
element->count++;
+ /* Avoid a wrap over of the count. */
+ if (! element->count)
+ element->count--;
}
DBUG_EXECUTE("check_tree", test_rb_tree(tree->root););
return element;
diff --git a/ndb/include/transporter/TransporterDefinitions.hpp b/ndb/include/transporter/TransporterDefinitions.hpp
index 18d1ec76a3c..e9c5ffa2c80 100644
--- a/ndb/include/transporter/TransporterDefinitions.hpp
+++ b/ndb/include/transporter/TransporterDefinitions.hpp
@@ -55,7 +55,7 @@ const Uint32 MAX_MESSAGE_SIZE = (12+4+4+(4*25)+(3*4)+4*4096);
* information specific to a transporter type.
*/
struct TransporterConfiguration {
- Uint32 port;
+ Int32 s_port; // negative port number implies dynamic port
const char *remoteHostName;
const char *localHostName;
NodeId remoteNodeId;
diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
index fd04ad393eb..eca886c8586 100644
--- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp
+++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
@@ -138,7 +138,7 @@ ConfigRetriever::getConfig(NdbMgmHandle m_handle){
setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
return 0;
}
-
+
return conf;
}
diff --git a/ndb/src/common/mgmcommon/IPCConfig.cpp b/ndb/src/common/mgmcommon/IPCConfig.cpp
index f45bc6ead54..f935f8ffab4 100644
--- a/ndb/src/common/mgmcommon/IPCConfig.cpp
+++ b/ndb/src/common/mgmcommon/IPCConfig.cpp
@@ -271,14 +271,12 @@ IPCConfig::configureTransporters(Uint32 nodeId,
If we're not using dynamic ports, we don't do anything.
*/
- if((int)server_port<0)
- server_port= -server_port;
conf.localNodeId = nodeId;
conf.remoteNodeId = remoteNodeId;
conf.checksum = checksum;
conf.signalId = sendSignalId;
- conf.port = server_port;
+ conf.s_port = server_port;
conf.localHostName = localHostName;
conf.remoteHostName = remoteHostName;
@@ -350,7 +348,7 @@ IPCConfig::configureTransporters(Uint32 nodeId,
if (!iter.get(CFG_TCP_PROXY, &proxy)) {
if (strlen(proxy) > 0 && nodeId2 == nodeId) {
// TODO handle host:port
- conf.port = atoi(proxy);
+ conf.s_port = atoi(proxy);
}
}
diff --git a/ndb/src/common/transporter/TransporterRegistry.cpp b/ndb/src/common/transporter/TransporterRegistry.cpp
index 5ffd3ac334e..3776bce7452 100644
--- a/ndb/src/common/transporter/TransporterRegistry.cpp
+++ b/ndb/src/common/transporter/TransporterRegistry.cpp
@@ -290,7 +290,7 @@ TransporterRegistry::createTCPTransporter(TransporterConfiguration *config) {
config->tcp.maxReceiveSize,
config->localHostName,
config->remoteHostName,
- config->port,
+ config->s_port,
config->isMgmConnection,
localNodeId,
config->remoteNodeId,
@@ -392,7 +392,7 @@ TransporterRegistry::createSCITransporter(TransporterConfiguration *config) {
SCI_Transporter * t = new SCI_Transporter(*this,
config->localHostName,
config->remoteHostName,
- config->port,
+ config->s_port,
config->isMgmConnection,
config->sci.sendLimit,
config->sci.bufferSize,
@@ -458,7 +458,7 @@ TransporterRegistry::createSHMTransporter(TransporterConfiguration *config) {
SHM_Transporter * t = new SHM_Transporter(*this,
config->localHostName,
config->remoteHostName,
- config->port,
+ config->s_port,
config->isMgmConnection,
localNodeId,
config->remoteNodeId,
@@ -1170,7 +1170,10 @@ TransporterRegistry::do_connect(NodeId node_id)
case DISCONNECTING:
break;
}
+ DBUG_ENTER("TransporterRegistry::do_connect");
+ DBUG_PRINT("info",("performStates[%d]=CONNECTING",node_id));
curr_state= CONNECTING;
+ DBUG_VOID_RETURN;
}
void
TransporterRegistry::do_disconnect(NodeId node_id)
@@ -1186,21 +1189,30 @@ TransporterRegistry::do_disconnect(NodeId node_id)
case DISCONNECTING:
return;
}
+ DBUG_ENTER("TransporterRegistry::do_disconnect");
+ DBUG_PRINT("info",("performStates[%d]=DISCONNECTING",node_id));
curr_state= DISCONNECTING;
+ DBUG_VOID_RETURN;
}
void
TransporterRegistry::report_connect(NodeId node_id)
{
+ DBUG_ENTER("TransporterRegistry::report_connect");
+ DBUG_PRINT("info",("performStates[%d]=CONNECTED",node_id));
performStates[node_id] = CONNECTED;
reportConnect(callbackObj, node_id);
+ DBUG_VOID_RETURN;
}
void
TransporterRegistry::report_disconnect(NodeId node_id, int errnum)
{
+ DBUG_ENTER("TransporterRegistry::report_disconnect");
+ DBUG_PRINT("info",("performStates[%d]=DISCONNECTED",node_id));
performStates[node_id] = DISCONNECTED;
reportDisconnect(callbackObj, node_id, errnum);
+ DBUG_VOID_RETURN;
}
void
diff --git a/ndb/src/common/util/version.c b/ndb/src/common/util/version.c
index 3157f3bc356..5883a709e96 100644
--- a/ndb/src/common/util/version.c
+++ b/ndb/src/common/util/version.c
@@ -90,6 +90,7 @@ void ndbSetOwnVersion() {}
#ifndef TEST_VERSION
struct NdbUpGradeCompatible ndbCompatibleTable_full[] = {
+ { MAKE_VERSION(5,0,NDB_VERSION_BUILD), MAKE_VERSION(5,0,3), UG_Range},
{ MAKE_VERSION(5,0,3), MAKE_VERSION(5,0,2), UG_Exact },
{ MAKE_VERSION(4,1,12), MAKE_VERSION(4,1,10), UG_Range },
{ MAKE_VERSION(4,1,10), MAKE_VERSION(4,1,9), UG_Exact },
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 16554955646..e4cce29ba30 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -763,11 +763,14 @@ Dbtc::set_timeout_value(Uint32 timeOut)
void
Dbtc::set_appl_timeout_value(Uint32 timeOut)
{
- timeOut /= 10;
- if (timeOut < ctimeOutValue) {
- jam();
- c_appl_timeout_value = ctimeOutValue;
- }//if
+ if (timeOut)
+ {
+ timeOut /= 10;
+ if (timeOut < ctimeOutValue) {
+ jam();
+ c_appl_timeout_value = ctimeOutValue;
+ }//if
+ }
c_appl_timeout_value = timeOut;
}
@@ -6286,7 +6289,8 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr)
particular state we will use the application timeout parameter rather
than the shorter Deadlock detection timeout.
*/
- if ((ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
+ if (c_appl_timeout_value == 0 ||
+ (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
jam();
return;
}//if
diff --git a/ndb/src/kernel/main.cpp b/ndb/src/kernel/main.cpp
index 543757153d3..f679646e14a 100644
--- a/ndb/src/kernel/main.cpp
+++ b/ndb/src/kernel/main.cpp
@@ -101,6 +101,12 @@ int main(int argc, char** argv)
*/
catchsigs(true);
+ /**
+ * We no longer need the mgm connection in this process
+ * (as we are the angel, not ndb)
+ */
+ theConfig->closeConfiguration();
+
int status = 0;
while(waitpid(child, &status, 0) != child);
if(WIFEXITED(status)){
diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp
index dad4459dbb8..a88d7d21820 100644
--- a/ndb/test/ndbapi/testBlobs.cpp
+++ b/ndb/test/ndbapi/testBlobs.cpp
@@ -1444,6 +1444,7 @@ testperf()
if (! testcase('p'))
return 0;
DBG("=== perf test ===");
+ g_bh1 = g_bh2 = 0;
g_ndb = new Ndb(g_ncc, "TEST_DB");
CHK(g_ndb->init() == 0);
CHK(g_ndb->waitUntilReady() == 0);
diff --git a/ndb/test/ndbapi/testTimeout.cpp b/ndb/test/ndbapi/testTimeout.cpp
index ac4f257f12c..b02751ec819 100644
--- a/ndb/test/ndbapi/testTimeout.cpp
+++ b/ndb/test/ndbapi/testTimeout.cpp
@@ -22,14 +22,14 @@
#include <NdbConfig.hpp>
#include <signaldata/DumpStateOrd.hpp>
-#define TIMEOUT 3000
-
+#define TIMEOUT (Uint32)3000
Uint32 g_org_timeout = 3000;
int
setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
NdbRestarter restarter;
-
+ int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
+
NdbConfig conf(GETNDB(step)->getNodeId()+1);
unsigned int nodeId = conf.getMasterNodeId();
if (!conf.getProperty(nodeId,
@@ -39,7 +39,7 @@ setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, TIMEOUT };
+ int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, timeout };
if(restarter.dumpStateAllNodes(val, 2) != 0){
return NDBT_FAILED;
}
@@ -95,8 +95,10 @@ int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){
int mul2 = ctx->getProperty("Op2", (Uint32)0);
int records = ctx->getNumRecords();
- int minSleep = (int)(TIMEOUT * 1.5);
- int maxSleep = TIMEOUT * 2;
+ int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
+
+ int minSleep = (int)(timeout * 1.5);
+ int maxSleep = timeout * 2;
HugoOperations hugoOps(*ctx->getTab());
Ndb* pNdb = GETNDB(step);
@@ -109,7 +111,7 @@ int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){
op1 = (op1 % 5);
op2 = (op2 % 5);
- ndbout << stepNo << ": TransactionInactiveTimeout="<< TIMEOUT
+ ndbout << stepNo << ": TransactionInactiveTimeout="<< timeout
<< ", minSleep="<<minSleep
<< ", maxSleep="<<maxSleep
<< ", op1=" << op1
@@ -211,8 +213,10 @@ int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
int loops = ctx->getNumLoops();
int stepNo = step->getStepNo();
- int maxSleep = (int)(TIMEOUT * 0.5);
- ndbout << "TransactionInactiveTimeout="<< TIMEOUT
+ int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
+
+ int maxSleep = (int)(timeout * 0.5);
+ ndbout << "TransactionInactiveTimeout="<< timeout
<< ", maxSleep="<<maxSleep<<endl;
@@ -242,6 +246,51 @@ int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
return result;
}
+int runDeadlockTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int stepNo = step->getStepNo();
+
+ Uint32 deadlock_timeout;
+ NdbConfig conf(GETNDB(step)->getNodeId()+1);
+ unsigned int nodeId = conf.getMasterNodeId();
+ if (!conf.getProperty(nodeId,
+ NODE_TYPE_DB,
+ CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
+ &deadlock_timeout)){
+ return NDBT_FAILED;
+ }
+
+
+ int do_sleep = (int)(deadlock_timeout * 0.5);
+
+
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+
+ for (int l = 0; l < loops && result == NDBT_OK; l++){
+
+ do{
+ // Commit transaction
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, stepNo) == 0);
+ CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
+
+ int sleep = deadlock_timeout * 1.5 + myRandom48(do_sleep);
+ ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
+ NdbSleep_MilliSleep(sleep);
+
+ // Expect that transaction has NOT timed-out
+ CHECK(hugoOps.execute_Commit(pNdb) == 0);
+
+ } while(false);
+
+ hugoOps.closeTransaction(pNdb);
+ }
+
+ return result;
+}
+
int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
int loops = ctx->getNumLoops();
@@ -295,6 +344,17 @@ TESTCASE("DontTimeoutTransaction",
FINALIZER(resetTransactionTimeout);
FINALIZER(runClearTable);
}
+TESTCASE("Bug11290",
+ "Setting TransactionInactiveTimeout to 0(zero) "\
+ "should result in infinite timeout, and not as "\
+ "was the bug, a timeout that is equal to the deadlock timeout"){
+ TC_PROPERTY("TransactionInactiveTimeout",(Uint32)0);
+ INITIALIZER(runLoadTable);
+ INITIALIZER(setTransactionTimeout);
+ STEPS(runDeadlockTimeoutTrans, 1);
+ FINALIZER(resetTransactionTimeout);
+ FINALIZER(runClearTable);
+}
TESTCASE("DontTimeoutTransaction5",
"Test that the transaction does not timeout "\
"if we sleep during the transaction. Use a sleep "\
diff --git a/netware/my_print_defaults.def b/netware/my_print_defaults.def
index 826981256b5..d88c5adf4cc 100644
--- a/netware/my_print_defaults.def
+++ b/netware/my_print_defaults.def
@@ -4,7 +4,8 @@
MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Print Defaults Tool"
-VERSION 4, 0
+VERSION 5, 0, 8
+STACKSIZE 32767
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysql_test_run.c b/netware/mysql_test_run.c
index 45b7c4719fb..e8293103974 100644
--- a/netware/mysql_test_run.c
+++ b/netware/mysql_test_run.c
@@ -343,6 +343,7 @@ void start_master()
add_arg(&al, "--character-sets-dir=%s", char_dir);
add_arg(&al, "--tmpdir=%s", mysql_tmp_dir);
add_arg(&al, "--language=%s", lang_dir);
+ add_arg(&al, "--log-bin-trust-routine-creators");
#ifdef DEBUG //only for debug builds
add_arg(&al, "--debug");
#endif
@@ -516,6 +517,7 @@ void start_slave()
add_arg(&al, "--master-retry-count=10");
add_arg(&al, "-O");
add_arg(&al, "slave_net_timeout=10");
+ add_arg(&al, "--log-bin-trust-routine-creators");
#ifdef DEBUG //only for debug builds
add_arg(&al, "--debug");
#endif
@@ -1164,6 +1166,8 @@ void setup(char *file)
setenv("MYSQL_CLIENT_TEST",file_path,1);
snprintf(file_path, PATH_MAX*2, "%s/mysql --no-defaults --user=root --port=%u ", bin_dir, master_port);
setenv("MYSQL",file_path,1);
+ snprintf(file_path, PATH_MAX*2, "%s/mysqlshow --no-defaults --user=root --port=%u", bin_dir, master_port);
+ setenv("MYSQL_SHOW",file_path,1);
}
/******************************************************************************
diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc
index b5d88873054..2357f97fd93 100644
--- a/server-tools/instance-manager/commands.cc
+++ b/server-tools/instance-manager/commands.cc
@@ -40,7 +40,7 @@
DESCRIPTION
Function to add a string to the buffer. It is different from
- store_to_string, which is used in the protocol.cc. The last
+ store_to_protocol_packet, which is used in the protocol.cc. The last
one also stores the length of the string in a special way.
This is required for MySQL client/server protocol support only.
@@ -104,11 +104,12 @@ int Show_instances::execute(struct st_net *net, ulong connection_id)
while ((instance= iterator.next()))
{
position= 0;
- store_to_string(&send_buff, instance->options.instance_name, &position);
+ store_to_protocol_packet(&send_buff, instance->options.instance_name,
+ &position);
if (instance->is_running())
- store_to_string(&send_buff, (char*) "online", &position);
+ store_to_protocol_packet(&send_buff, (char*) "online", &position);
else
- store_to_string(&send_buff, (char*) "offline", &position);
+ store_to_protocol_packet(&send_buff, (char*) "offline", &position);
if (my_net_write(net, send_buff.buffer, (uint) position))
goto err;
}
@@ -199,18 +200,19 @@ int Show_instance_status::execute(struct st_net *net,
{
Instance *instance;
- store_to_string(&send_buff, (char*) instance_name, &position);
+ store_to_protocol_packet(&send_buff, (char*) instance_name, &position);
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
goto err;
if (instance->is_running())
- store_to_string(&send_buff, (char*) "online", &position);
+ store_to_protocol_packet(&send_buff, (char*) "online", &position);
else
- store_to_string(&send_buff, (char*) "offline", &position);
+ store_to_protocol_packet(&send_buff, (char*) "offline", &position);
if (instance->options.mysqld_version)
- store_to_string(&send_buff, instance->options.mysqld_version, &position);
+ store_to_protocol_packet(&send_buff, instance->options.mysqld_version,
+ &position);
else
- store_to_string(&send_buff, (char*) "unknown", &position);
+ store_to_protocol_packet(&send_buff, (char*) "unknown", &position);
if (send_buff.is_error() ||
@@ -272,17 +274,17 @@ int Show_instance_options::execute(struct st_net *net, ulong connection_id)
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
goto err;
- store_to_string(&send_buff, (char*) "instance_name", &position);
- store_to_string(&send_buff, (char*) instance_name, &position);
+ store_to_protocol_packet(&send_buff, (char*) "instance_name", &position);
+ store_to_protocol_packet(&send_buff, (char*) instance_name, &position);
if (my_net_write(net, send_buff.buffer, (uint) position))
goto err;
if ((instance->options.mysqld_path))
{
position= 0;
- store_to_string(&send_buff, (char*) "mysqld-path", &position);
- store_to_string(&send_buff,
- (char*) instance->options.mysqld_path,
- &position);
+ store_to_protocol_packet(&send_buff, (char*) "mysqld-path", &position);
+ store_to_protocol_packet(&send_buff,
+ (char*) instance->options.mysqld_path,
+ &position);
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
goto err;
@@ -291,8 +293,8 @@ int Show_instance_options::execute(struct st_net *net, ulong connection_id)
if ((instance->options.nonguarded))
{
position= 0;
- store_to_string(&send_buff, (char*) "nonguarded", &position);
- store_to_string(&send_buff, "", &position);
+ store_to_protocol_packet(&send_buff, (char*) "nonguarded", &position);
+ store_to_protocol_packet(&send_buff, "", &position);
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
goto err;
@@ -310,13 +312,16 @@ int Show_instance_options::execute(struct st_net *net, ulong connection_id)
if (option_value != NULL)
{
*option_value= 0;
- store_to_string(&send_buff, tmp_option + 2, &position);
- store_to_string(&send_buff, option_value + 1, &position);
+ store_to_protocol_packet(&send_buff, tmp_option + 2, &position);
+ store_to_protocol_packet(&send_buff, option_value + 1, &position);
/* join name and the value into the same option again */
*option_value= '=';
}
else
- store_to_string(&send_buff, tmp_option + 2, &position);
+ {
+ store_to_protocol_packet(&send_buff, tmp_option + 2, &position);
+ store_to_protocol_packet(&send_buff, "", &position);
+ }
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
@@ -478,7 +483,7 @@ int Show_instance_log::execute(struct st_net *net, ulong connection_id)
char *bf= (char*) malloc(sizeof(char)*buff_size);
if ((read_len= my_read(fd, bf, buff_size, MYF(0))) < 0)
return ER_READ_FILE;
- store_to_string(&send_buff, (char*) bf, &position, read_len);
+ store_to_protocol_packet(&send_buff, (char*) bf, &position, read_len);
close(fd);
}
else
@@ -593,19 +598,19 @@ int Show_instance_log_files::execute(struct st_net *net, ulong connection_id)
position= 0;
/* store the type of the log in the send buffer */
- store_to_string(&send_buff, log_files->name, &position);
+ store_to_protocol_packet(&send_buff, log_files->name, &position);
if (stat(log_files->value, &file_stat))
{
- store_to_string(&send_buff, "", &position);
- store_to_string(&send_buff, (char*) "0", &position);
+ store_to_protocol_packet(&send_buff, "", &position);
+ store_to_protocol_packet(&send_buff, (char*) "0", &position);
}
else if (S_ISREG(file_stat.st_mode))
{
- store_to_string(&send_buff,
- (char*) log_files->value,
- &position);
+ store_to_protocol_packet(&send_buff,
+ (char*) log_files->value,
+ &position);
int10_to_str(file_stat.st_size, buff, 10);
- store_to_string(&send_buff, (char*) buff, &position);
+ store_to_protocol_packet(&send_buff, (char*) buff, &position);
}
if (my_net_write(net, send_buff.buffer, (uint) position))
diff --git a/server-tools/instance-manager/protocol.cc b/server-tools/instance-manager/protocol.cc
index 62de48d0619..4b46d091c3f 100644
--- a/server-tools/instance-manager/protocol.cc
+++ b/server-tools/instance-manager/protocol.cc
@@ -58,7 +58,7 @@ int net_send_ok(struct st_net *net, unsigned long connection_id,
if (message != NULL)
{
buff.reserve(position, 9 + strlen(message));
- store_to_string(&buff, message, &position);
+ store_to_protocol_packet(&buff, message, &position);
}
return my_net_write(net, buff.buffer, position) || net_flush(net);
@@ -117,8 +117,8 @@ char *net_store_length(char *pkg, uint length)
}
-int store_to_string(Buffer *buf, const char *string, uint *position,
- uint string_len)
+int store_to_protocol_packet(Buffer *buf, const char *string, uint *position,
+ uint string_len)
{
uint currpos;
@@ -137,12 +137,12 @@ err:
}
-int store_to_string(Buffer *buf, const char *string, uint *position)
+int store_to_protocol_packet(Buffer *buf, const char *string, uint *position)
{
uint string_len;
string_len= strlen(string);
- return store_to_string(buf, string, position, string_len);
+ return store_to_protocol_packet(buf, string, position, string_len);
}
@@ -176,21 +176,28 @@ int send_fields(struct st_net *net, LIST *fields)
position= 0;
field= (NAME_WITH_LENGTH *) tmp->data;
- store_to_string(&send_buff, (char*) "", &position); /* catalog name */
- store_to_string(&send_buff, (char*) "", &position); /* db name */
- store_to_string(&send_buff, (char*) "", &position); /* table name */
- store_to_string(&send_buff, (char*) "", &position); /* table name alias */
- store_to_string(&send_buff, field->name, &position); /* column name */
- store_to_string(&send_buff, field->name, &position); /* column name alias */
+ store_to_protocol_packet(&send_buff,
+ (char*) "", &position); /* catalog name */
+ store_to_protocol_packet(&send_buff,
+ (char*) "", &position); /* db name */
+ store_to_protocol_packet(&send_buff,
+ (char*) "", &position); /* table name */
+ store_to_protocol_packet(&send_buff,
+ (char*) "", &position); /* table name alias */
+ store_to_protocol_packet(&send_buff,
+ field->name, &position); /* column name */
+ store_to_protocol_packet(&send_buff,
+ field->name, &position); /* column name alias */
send_buff.reserve(position, 12);
if (send_buff.is_error())
goto err;
send_buff.buffer[position++]= 12;
- int2store(send_buff.buffer + position, 1); /* charsetnr */
- int4store(send_buff.buffer + position + 2, field->length); /* field length */
- send_buff.buffer[position+6]= FIELD_TYPE_STRING; /* type */
- int2store(send_buff.buffer + position + 7, 0); /* flags */
- send_buff.buffer[position + 9]= (char) 0; /* decimals */
+ int2store(send_buff.buffer + position, 1); /* charsetnr */
+ int4store(send_buff.buffer + position + 2,
+ field->length); /* field length */
+ send_buff.buffer[position+6]= FIELD_TYPE_STRING; /* type */
+ int2store(send_buff.buffer + position + 7, 0); /* flags */
+ send_buff.buffer[position + 9]= (char) 0; /* decimals */
send_buff.buffer[position + 10]= 0;
send_buff.buffer[position + 11]= 0;
position+= 12;
diff --git a/server-tools/instance-manager/protocol.h b/server-tools/instance-manager/protocol.h
index a2ed9a31889..f38eac6b079 100644
--- a/server-tools/instance-manager/protocol.h
+++ b/server-tools/instance-manager/protocol.h
@@ -41,10 +41,10 @@ int send_fields(struct st_net *net, LIST *fields);
char *net_store_length(char *pkg, uint length);
-int store_to_string(Buffer *buf, const char *string, uint *position);
+int store_to_protocol_packet(Buffer *buf, const char *string, uint *position);
-int store_to_string(Buffer *buf, const char *string, uint *position,
- uint string_len);
+int store_to_protocol_packet(Buffer *buf, const char *string, uint *position,
+ uint string_len);
int send_eof(struct st_net *net);
diff --git a/sql-common/client.c b/sql-common/client.c
index 0bebcb0065d..c736acae857 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -2130,7 +2130,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
for (; ptr<end; ptr++)
{
MYSQL_RES *res;
- if (mysql_real_query(mysql,*ptr, strlen(*ptr)))
+ if (mysql_real_query(mysql,*ptr, (ulong) strlen(*ptr)))
goto error;
if (mysql->fields)
{
diff --git a/sql/Makefile.am b/sql/Makefile.am
index b506d2a767b..524ec93a6a9 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -111,8 +111,8 @@ DEFS = -DMYSQL_SERVER \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
@DEFS@
-# Don't put lex_hash.h in BUILT_SOURCES as this will give infinite recursion
-BUILT_SOURCES = sql_yacc.cc sql_yacc.h
+
+BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h
EXTRA_DIST = udf_example.cc $(BUILT_SOURCES)
DISTCLEANFILES = lex_hash.h
AM_YFLAGS = -d
@@ -131,9 +131,6 @@ link_sources: mysql_tzinfo_to_sql.cc
rm -f my_time.c
@LN_CP_F@ ../sql-common/my_time.c my_time.c
-gen_lex_hash.o: gen_lex_hash.cc lex.h
- $(CXXCOMPILE) -c $(INCLUDES) $<
-
mysql_tzinfo_to_sql.o: $(mysql_tzinfo_to_sql_SOURCES)
$(CXXCOMPILE) -c $(INCLUDES) -DTZINFO2SQL $<
@@ -148,13 +145,9 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS)
@echo "If it fails, re-run configure with --with-low-memory"
$(CXXCOMPILE) $(LM_CFLAGS) -c $<
-lex_hash.h: lex.h gen_lex_hash.cc sql_yacc.h
- $(MAKE) gen_lex_hash$(EXEEXT)
+lex_hash.h: gen_lex_hash$(EXEEXT)
./gen_lex_hash$(EXEEXT) > $@
-# Hack to ensure that lex_hash.h is built early
-sql_lex.o: lex_hash.h
-
# For testing of udf_example.so; Works on platforms with gcc
# (This is not part of our build process but only provided as an example)
udf_example.so: udf_example.cc
diff --git a/sql/field.cc b/sql/field.cc
index 89ef25475ff..fb244de4275 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -38,7 +38,7 @@
Instansiate templates and static variables
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<create_field>;
template class List_iterator<create_field>;
#endif
@@ -1920,7 +1920,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
int_digits_added_zeros=0;
}
}
- tmp_uint= (tmp_dec+(int_digits_end-int_digits_from)+
+ tmp_uint= (uint) (tmp_dec+(int_digits_end-int_digits_from)+
(uint)(frac_digits_from-int_digits_tail_from)+
int_digits_added_zeros);
}
@@ -3317,12 +3317,12 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
}
if (error)
{
- error= 1;
+ error= error != MY_ERRNO_EDOM ? 1 : 2;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
}
else if (from+len != end && table->in_use->count_cuted_fields &&
check_int(from,len,end,cs))
- error= 1;
+ error= 2;
store_tmp= (long) tmp;
#ifdef WORDS_BIGENDIAN
@@ -3584,7 +3584,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
}
else if (from+len != end && table->in_use->count_cuted_fields &&
check_int(from,len,end,cs))
- error= 1;
+ error= 2;
#ifdef WORDS_BIGENDIAN
if (table->s->db_low_byte_first)
{
@@ -3806,7 +3806,7 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
(error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1);
- error= 1;
+ error= error ? 1 : 2;
}
Field_float::store(nr);
return error;
@@ -4093,7 +4093,7 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
(error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1);
- error= 1;
+ error= error ? 1 : 2;
}
Field_double::store(nr);
return error;
@@ -4495,6 +4495,8 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
error= 1;
}
}
+ if (error > 1)
+ error= 2;
#ifdef WORDS_BIGENDIAN
if (table->s->db_low_byte_first)
@@ -4791,7 +4793,7 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
if (str_to_time(from, len, &ltime, &error))
{
tmp=0L;
- error= 1;
+ error= 2;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
from, len, MYSQL_TIMESTAMP_TIME, 1);
}
@@ -4813,6 +4815,8 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
from, len, MYSQL_TIMESTAMP_TIME, !error);
error= 1;
}
+ if (error > 1)
+ error= 2;
}
if (ltime.neg)
@@ -5149,7 +5153,7 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
&error) <= MYSQL_TIMESTAMP_ERROR)
{
tmp=0;
- error= 1;
+ error= 2;
}
else
tmp=(uint32) l_time.year*10000L + (uint32) (l_time.month*100+l_time.day);
@@ -5353,7 +5357,7 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
&error) <= MYSQL_TIMESTAMP_ERROR)
{
tmp=0L;
- error= 1;
+ error= 2;
}
else
tmp= l_time.day + l_time.month*32 + l_time.year*16*32;
@@ -5836,7 +5840,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
from= tmpstr.ptr();
length= tmpstr.length();
if (conv_errors)
- error= 1;
+ error= 2;
}
/*
@@ -5860,7 +5864,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
from+= field_charset->cset->scan(field_charset, from, end,
MY_SEQ_SPACES);
if (from != end)
- error= 1;
+ error= 2;
}
if (error)
{
@@ -5956,14 +5960,6 @@ longlong Field_string::val_int(void)
}
-my_decimal *Field_longstr::val_decimal(my_decimal *decimal_value)
-{
- str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(),
- decimal_value);
- return decimal_value;
-}
-
-
String *Field_string::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
@@ -5975,6 +5971,14 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
}
+my_decimal *Field_string::val_decimal(my_decimal *decimal_value)
+{
+ str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(),
+ decimal_value);
+ return decimal_value;
+}
+
+
int Field_string::cmp(const char *a_ptr, const char *b_ptr)
{
uint a_len, b_len;
@@ -6242,7 +6246,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
table->in_use->abort_on_warning)
error_code= ER_DATA_TOO_LONG;
set_warning(level, error_code, 1);
- return 1;
+ return 2;
}
return 0;
}
@@ -6288,6 +6292,15 @@ String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
}
+my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value)
+{
+ uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
+ str2my_decimal(E_DEC_FATAL_ERROR, ptr+length_bytes, length, charset(),
+ decimal_value);
+ return decimal_value;
+}
+
+
int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
{
uint a_length, b_length;
@@ -6813,7 +6826,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
from= tmpstr.ptr();
length= tmpstr.length();
if (conv_errors)
- error= 1;
+ error= 2;
}
copy_length= max_data_length();
@@ -6828,7 +6841,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
copy_length,
&well_formed_error);
if (copy_length < length)
- error= 1;
+ error= 2;
Field_blob::store_length(copy_length);
if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH)
{ // Must make a copy
@@ -6906,6 +6919,18 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
}
+my_decimal *Field_blob::val_decimal(my_decimal *decimal_value)
+{
+ char *blob;
+ memcpy_fixed(&blob, ptr+packlength, sizeof(char*));
+ if (!blob)
+ blob= "";
+ str2my_decimal(E_DEC_FATAL_ERROR, blob, get_length(ptr), charset(),
+ decimal_value);
+ return decimal_value;
+}
+
+
int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
uint32 b_length)
{
@@ -7734,9 +7759,9 @@ bool Field_enum::eq_def(Field *field)
for (uint i=0 ; i < from_lib->count ; i++)
if (my_strnncoll(field_charset,
(const uchar*)typelib->type_names[i],
- strlen(typelib->type_names[i]),
+ (uint) strlen(typelib->type_names[i]),
(const uchar*)from_lib->type_names[i],
- strlen(from_lib->type_names[i])))
+ (uint) strlen(from_lib->type_names[i])))
return 0;
return 1;
}
@@ -8594,7 +8619,8 @@ Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, uint code,
{
char str_nr[22];
char *str_end= longlong10_to_str(nr, str_nr, -10);
- make_truncated_value_warning(table->in_use, str_nr, str_end - str_nr,
+ make_truncated_value_warning(table->in_use, str_nr,
+ (uint) (str_end - str_nr),
ts_type, field_name);
}
}
diff --git a/sql/field.h b/sql/field.h
index a522558a8d7..2b1229744c2 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -25,6 +25,7 @@
#endif
#define NOT_FIXED_DEC 31
+#define DATETIME_DEC 6
class Send_field;
class Protocol;
@@ -381,7 +382,6 @@ public:
field_name_arg, table_arg, charset)
{}
- my_decimal *val_decimal(my_decimal *);
int store_decimal(const my_decimal *d);
};
@@ -942,6 +942,7 @@ public:
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
#endif
enum Item_result cmp_type () const { return INT_RESULT; }
+ uint decimals() const { return DATETIME_DEC; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr);
@@ -993,6 +994,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ my_decimal *val_decimal(my_decimal *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
void sql_type(String &str) const;
@@ -1051,6 +1053,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ my_decimal *val_decimal(my_decimal *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
void get_key_image(char *buff,uint length, imagetype type);
@@ -1106,6 +1109,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ my_decimal *val_decimal(my_decimal *);
int cmp(const char *,const char*);
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
@@ -1284,7 +1288,7 @@ public:
enum_field_types type() const { return FIELD_TYPE_BIT; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; }
uint32 key_length() const { return (uint32) field_length + (bit_len > 0); }
- uint32 max_length() { return (uint32) field_length + (bit_len > 0); }
+ uint32 max_length() { return (uint32) field_length * 8 + bit_len; }
uint size_of() const { return sizeof(*this); }
Item_result result_type () const { return INT_RESULT; }
void reset(void) { bzero(ptr, field_length); }
@@ -1316,6 +1320,11 @@ public:
Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
+ void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg)
+ {
+ bit_ptr= bit_ptr_arg;
+ bit_ofs= bit_ofs_arg;
+ }
};
@@ -1327,6 +1336,7 @@ public:
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg);
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
+ uint32 max_length() { return (uint32) create_length; }
uint size_of() const { return sizeof(*this); }
int store(const char *to, uint length, CHARSET_INFO *charset);
int store(double nr) { return Field_bit::store(nr); }
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 30ebd8d59e1..75da43afed5 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -631,7 +631,7 @@ static void make_sortkey(register SORTPARAM *param,
*to++=1;
/* All item->str() to use some extra byte for end null.. */
String tmp((char*) to,sort_field->length+4,cs);
- String *res=item->val_str(&tmp);
+ String *res= item->str_result(&tmp);
if (!res)
{
if (maybe_null)
@@ -673,8 +673,8 @@ static void make_sortkey(register SORTPARAM *param,
}
case INT_RESULT:
{
- longlong value=item->val_int();
- if (maybe_null)
+ longlong value= item->val_int_result();
+ if (maybe_null)
{
*to++=1; /* purecov: inspected */
if (item->null_value)
@@ -715,7 +715,7 @@ static void make_sortkey(register SORTPARAM *param,
}
case DECIMAL_RESULT:
{
- my_decimal dec_buf, *dec_val= item->val_decimal(&dec_buf);
+ my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
if (maybe_null)
{
if (item->null_value)
@@ -733,7 +733,7 @@ static void make_sortkey(register SORTPARAM *param,
}
case REAL_RESULT:
{
- double value= item->val_real();
+ double value= item->val_result();
if (maybe_null)
{
if (item->null_value)
diff --git a/sql/gstream.cc b/sql/gstream.cc
index f7d11d76b0c..4083cb2fe71 100644
--- a/sql/gstream.cc
+++ b/sql/gstream.cc
@@ -83,7 +83,7 @@ bool Gis_read_stream::get_next_number(double *d)
}
*d = my_strntod(m_charset, (char *)m_cur,
- m_limit-m_cur, &endptr, &err);
+ (uint) (m_limit-m_cur), &endptr, &err);
if (err)
return 1;
if (endptr)
@@ -115,6 +115,6 @@ bool Gis_read_stream::check_next_symbol(char symbol)
void Gis_read_stream::set_error_msg(const char *msg)
{
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));
+ m_err_msg= (char *) my_realloc(m_err_msg, (uint) len + 1, MYF(MY_ALLOW_ZERO_PTR));
memcpy(m_err_msg, msg, len + 1);
}
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index 89210a2f3cd..77db17608bc 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -462,6 +462,12 @@ static int check_foreign_data_source(FEDERATED_SHARE *share)
}
else
{
+ /*
+ Since we do not support transactions at this version, we can let the client
+ API silently reconnect. For future versions, we will need more logic to deal
+ with transactions
+ */
+ mysql->reconnect= 1;
/*
Note: I am not using INORMATION_SCHEMA because this needs to work with < 5.0
if we can connect, then make sure the table exists
@@ -988,6 +994,12 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked)
my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql));
DBUG_RETURN(ER_CONNECT_TO_MASTER);
}
+ /*
+ Since we do not support transactions at this version, we can let the client
+ API silently reconnect. For future versions, we will need more logic to deal
+ with transactions
+ */
+ mysql->reconnect= 1;
DBUG_RETURN(0);
}
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index cd655eeb0a9..6e609a94be3 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -65,7 +65,15 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
/* Initialize variables for the opened table */
set_keys_for_scanning();
- update_key_stats();
+ /*
+ We cannot run update_key_stats() here because we do not have a
+ lock on the table. The 'records' count might just be changed
+ temporarily at this moment and we might get wrong statistics (Bug
+ #10178). Instead we request for update. This will be done in
+ ha_heap::info(), which is always called before key statistics are
+ used.
+ */
+ key_stats_ok= FALSE;
}
return (file ? 0 : 1);
}
@@ -118,6 +126,8 @@ void ha_heap::update_key_stats()
}
}
records_changed= 0;
+ /* At the end of update_key_stats() we can proudly claim they are OK. */
+ key_stats_ok= TRUE;
}
@@ -132,7 +142,7 @@ int ha_heap::write_row(byte * buf)
res= heap_write(file,buf);
if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
file->s->records))
- update_key_stats();
+ key_stats_ok= FALSE;
return res;
}
@@ -145,7 +155,7 @@ int ha_heap::update_row(const byte * old_data, byte * new_data)
res= heap_update(file,old_data,new_data);
if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
file->s->records)
- update_key_stats();
+ key_stats_ok= FALSE;
return res;
}
@@ -156,7 +166,7 @@ int ha_heap::delete_row(const byte * buf)
res= heap_delete(file,buf);
if (!res && table->s->tmp_table == NO_TMP_TABLE &&
++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
- update_key_stats();
+ key_stats_ok= FALSE;
return res;
}
@@ -278,6 +288,13 @@ void ha_heap::info(uint flag)
delete_length= info.deleted * info.reclength;
if (flag & HA_STATUS_AUTO)
auto_increment_value= info.auto_increment;
+ /*
+ If info() is called for the first time after open(), we will still
+ have to update the key statistics. Hoping that a table lock is now
+ in place.
+ */
+ if (! key_stats_ok)
+ update_key_stats();
}
int ha_heap::extra(enum ha_extra_function operation)
@@ -289,7 +306,7 @@ int ha_heap::delete_all_rows()
{
heap_clear(file);
if (table->s->tmp_table == NO_TMP_TABLE)
- update_key_stats();
+ key_stats_ok= FALSE;
return 0;
}
@@ -448,6 +465,9 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
min_key->flag != HA_READ_KEY_EXACT ||
max_key->flag != HA_READ_AFTER_KEY)
return HA_POS_ERROR; // Can only use exact keys
+
+ /* Assert that info() did run. We need current statistics here. */
+ DBUG_ASSERT(key_stats_ok);
return key->rec_per_key[key->key_parts-1];
}
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index 2aa065e0d96..7a97c727049 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -29,8 +29,10 @@ class ha_heap: public handler
key_map btree_keys;
/* number of records changed since last statistics update */
uint records_changed;
+ bool key_stats_ok;
public:
- ha_heap(TABLE *table): handler(table), file(0), records_changed(0) {}
+ ha_heap(TABLE *table): handler(table), file(0), records_changed(0),
+ key_stats_ok(0) {}
~ha_heap() {}
const char *table_type() const
{
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 4ed005874f1..db354066849 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -146,8 +146,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
innobase_buffer_pool_awe_mem_mb,
innobase_buffer_pool_size, innobase_additional_mem_pool_size,
innobase_file_io_threads, innobase_lock_wait_timeout,
- innobase_thread_concurrency, innobase_force_recovery,
- innobase_open_files;
+ innobase_force_recovery, innobase_open_files;
/* The default values for the following char* start-up parameters
are determined in innobase_init below: */
@@ -327,7 +326,7 @@ innodb_srv_conc_enter_innodb(
/*=========================*/
trx_t* trx) /* in: transaction handle */
{
- if (srv_thread_concurrency >= 500) {
+ if (UNIV_LIKELY(srv_thread_concurrency >= 20)) {
return;
}
@@ -344,7 +343,7 @@ innodb_srv_conc_exit_innodb(
/*========================*/
trx_t* trx) /* in: transaction handle */
{
- if (srv_thread_concurrency >= 500) {
+ if (UNIV_LIKELY(srv_thread_concurrency >= 20)) {
return;
}
@@ -564,7 +563,7 @@ innobase_mysql_print_thd(
thd = (const THD*) input_thd;
fprintf(f, "MySQL thread id %lu, query id %lu",
- thd->thread_id, thd->query_id);
+ thd->thread_id, (ulong) thd->query_id);
if (thd->host) {
putc(' ', f);
fputs(thd->host, f);
@@ -1041,7 +1040,19 @@ mysql_get_identifier_quote_char(
return(EOF);
}
return(get_quote_char_for_identifier((THD*) trx->mysql_thd,
- name, namelen));
+ name, (int) namelen));
+}
+
+/**************************************************************************
+Determines if the currently running transaction has been interrupted. */
+extern "C"
+ibool
+trx_is_interrupted(
+/*===============*/
+ /* out: TRUE if interrupted */
+ trx_t* trx) /* in: transaction */
+{
+ return(trx && trx->mysql_thd && ((THD*) trx->mysql_thd)->killed);
}
/**************************************************************************
@@ -1302,8 +1313,8 @@ innobase_init(void)
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
- data_mysql_latin1_swedish_charset_coll =
- (ulint)my_charset_latin1.number;
+ ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
+ my_charset_latin1.number);
/* Store the latin1_swedish_ci character ordering table to InnoDB. For
non-latin1_swedish_ci charsets we use the MySQL comparison functions,
@@ -1794,7 +1805,7 @@ try_again:
fprintf(stderr,
"InnoDB: This transaction needs it to be sent up to\n"
"InnoDB: file %s, position %lu\n", trx->repl_wait_binlog_name,
- (uint)trx->repl_wait_binlog_pos);
+ (ulong)trx->repl_wait_binlog_pos);
innobase_repl_state = 0;
@@ -2022,7 +2033,7 @@ innobase_rollback_to_savepoint(
longlong2str((ulonglong)savepoint, name, 36);
- error = trx_rollback_to_savepoint_for_mysql(trx, name,
+ error = (int) trx_rollback_to_savepoint_for_mysql(trx, name,
&mysql_binlog_cache_pos);
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
@@ -2051,7 +2062,7 @@ innobase_release_savepoint(
longlong2str((ulonglong)savepoint, name, 36);
- error = trx_release_savepoint_for_mysql(trx, name);
+ error = (int) trx_release_savepoint_for_mysql(trx, name);
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
@@ -2092,7 +2103,7 @@ innobase_savepoint(
char name[64];
longlong2str((ulonglong)savepoint,name,36);
- error = trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
+ error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
@@ -2663,7 +2674,7 @@ innobase_read_from_2_little_endian(
/* out: value */
const mysql_byte* buf) /* in: from where to read */
{
- return((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
+ return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
}
/***********************************************************************
@@ -2867,6 +2878,8 @@ build_template(
ibool fetch_all_in_key = FALSE;
ibool fetch_primary_key_cols = FALSE;
ulint i;
+ /* byte offset of the end of last requested column */
+ ulint mysql_prefix_len = 0;
if (prebuilt->select_lock_type == LOCK_X) {
/* We always retrieve the whole clustered index record if we
@@ -2987,6 +3000,11 @@ build_template(
get_field_offset(table, field);
templ->mysql_col_len = (ulint) field->pack_length();
+ if (mysql_prefix_len < templ->mysql_col_offset
+ + templ->mysql_col_len) {
+ mysql_prefix_len = templ->mysql_col_offset
+ + templ->mysql_col_len;
+ }
templ->type = index->table->cols[i].type.mtype;
templ->mysql_type = (ulint)field->type();
@@ -3009,6 +3027,7 @@ skip_field:
}
prebuilt->n_template = n_requested_fields;
+ prebuilt->mysql_prefix_len = mysql_prefix_len;
if (index != clust_index && prebuilt->need_to_access_clustered) {
/* Change rec_field_no's to correspond to the clustered index
@@ -3080,7 +3099,7 @@ ha_innobase::write_row(
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
dict_table_t* src_table;
- ibool mode;
+ ulint mode;
num_write_row = 0;
@@ -3743,7 +3762,7 @@ ha_innobase::index_read(
match_mode = ROW_SEL_EXACT_PREFIX;
}
- last_match_mode = match_mode;
+ last_match_mode = (uint) match_mode;
innodb_srv_conc_enter_innodb(prebuilt->trx);
@@ -3763,7 +3782,7 @@ ha_innobase::index_read(
error = HA_ERR_KEY_NOT_FOUND;
table->status = STATUS_NOT_FOUND;
} else {
- error = convert_error_code_to_mysql(ret, user_thd);
+ error = convert_error_code_to_mysql((int) ret, user_thd);
table->status = STATUS_NOT_FOUND;
}
@@ -3915,7 +3934,7 @@ ha_innobase::general_fetch(
error = HA_ERR_END_OF_FILE;
table->status = STATUS_NOT_FOUND;
} else {
- error = convert_error_code_to_mysql(ret, user_thd);
+ error = convert_error_code_to_mysql((int) ret, user_thd);
table->status = STATUS_NOT_FOUND;
}
@@ -4864,7 +4883,7 @@ innobase_drop_database(
}
ptr++;
- namebuf = my_malloc(len + 2, MYF(0));
+ namebuf = my_malloc((uint) len + 2, MYF(0));
memcpy(namebuf, ptr, len);
namebuf[len] = '/';
@@ -5430,7 +5449,7 @@ ha_innobase::update_table_comment(
info on foreign keys */
const char* comment)/* in: table comment defined by user */
{
- uint length = strlen(comment);
+ uint length = (uint) strlen(comment);
char* str;
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
@@ -5482,7 +5501,7 @@ ha_innobase::update_table_comment(
*pos++ = ' ';
}
rewind(file);
- flen = fread(pos, 1, flen, file);
+ flen = (uint) fread(pos, 1, flen, file);
pos[flen] = 0;
}
@@ -5545,7 +5564,7 @@ ha_innobase::get_foreign_key_create_info(void)
if (str) {
rewind(file);
- flen = fread(str, 1, flen, file);
+ flen = (uint) fread(str, 1, flen, file);
str[flen] = 0;
}
@@ -5585,8 +5604,8 @@ ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
while (tmp_buff[i] != '/')
i++;
tmp_buff+= i + 1;
- f_key_info.forein_id= make_lex_string(thd, 0,
- tmp_buff, strlen(tmp_buff), 1);
+ f_key_info.forein_id= make_lex_string(thd, 0, tmp_buff,
+ (uint) strlen(tmp_buff), 1);
tmp_buff= foreign->referenced_table_name;
i= 0;
while (tmp_buff[i] != '/')
@@ -5594,16 +5613,16 @@ ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
f_key_info.referenced_db= make_lex_string(thd, 0,
tmp_buff, i, 1);
tmp_buff+= i + 1;
- f_key_info.referenced_table= make_lex_string(thd, 0,
- tmp_buff, strlen(tmp_buff), 1);
+ f_key_info.referenced_table= make_lex_string(thd, 0, tmp_buff,
+ (uint) strlen(tmp_buff), 1);
for (i= 0;;)
{
tmp_buff= foreign->foreign_col_names[i];
- name= make_lex_string(thd, name, tmp_buff, strlen(tmp_buff), 1);
+ name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1);
f_key_info.foreign_fields.push_back(name);
tmp_buff= foreign->referenced_col_names[i];
- name= make_lex_string(thd, name, tmp_buff, strlen(tmp_buff), 1);
+ name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1);
f_key_info.referenced_fields.push_back(name);
if (++i >= foreign->n_fields)
break;
@@ -5991,12 +6010,12 @@ ha_innobase::external_lock(
ulint error;
error = row_lock_table_for_mysql(prebuilt,
- NULL, LOCK_TABLE_EXP);
+ NULL, 0);
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(
- error, user_thd);
- DBUG_RETURN(error);
+ (int) error, user_thd);
+ DBUG_RETURN((int) error);
}
}
@@ -6011,9 +6030,6 @@ ha_innobase::external_lock(
trx->n_mysql_tables_in_use--;
prebuilt->mysql_has_locked = FALSE;
- if (trx->n_lock_table_exp) {
- row_unlock_tables_for_mysql(trx);
- }
/* If the MySQL lock count drops to zero we know that the current SQL
statement has ended */
@@ -6055,7 +6071,7 @@ user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
int
ha_innobase::transactional_table_lock(
/*==================================*/
- /* out: 0 */
+ /* out: error code */
THD* thd, /* in: handle to the user thread */
int lock_type) /* in: lock type */
{
@@ -6119,12 +6135,11 @@ ha_innobase::transactional_table_lock(
if (thd->in_lock_tables && thd->variables.innodb_table_locks) {
ulint error = DB_SUCCESS;
- error = row_lock_table_for_mysql(prebuilt,NULL,
- LOCK_TABLE_TRANSACTIONAL);
+ error = row_lock_table_for_mysql(prebuilt, NULL, 0);
if (error != DB_SUCCESS) {
- error = convert_error_code_to_mysql(error, user_thd);
- DBUG_RETURN(error);
+ error = convert_error_code_to_mysql((int) error, user_thd);
+ DBUG_RETURN((int) error);
}
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
@@ -6214,22 +6229,22 @@ innodb_show_status(
rewind(srv_monitor_file);
if (flen < MAX_STATUS_SIZE) {
/* Display the entire output. */
- flen = fread(str, 1, flen, srv_monitor_file);
+ flen = (long) fread(str, 1, flen, srv_monitor_file);
} else if (trx_list_end < (ulint) flen
&& trx_list_start < trx_list_end
&& trx_list_start + (flen - trx_list_end)
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
/* Omit the beginning of the list of active transactions. */
- long len = fread(str, 1, trx_list_start, srv_monitor_file);
+ long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
len += sizeof truncated_msg - 1;
usable_len = (MAX_STATUS_SIZE - 1) - len;
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
- len += fread(str + len, 1, usable_len, srv_monitor_file);
+ len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
flen = len;
} else {
/* Omit the end of the output. */
- flen = fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
+ flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
}
mutex_exit_noninline(&srv_monitor_file_mutex);
@@ -6791,7 +6806,7 @@ innobase_get_at_most_n_mbchars(
ulint n_chars; /* number of characters in prefix */
CHARSET_INFO* charset; /* charset used in the field */
- charset = get_charset(charset_id, MYF(MY_WME));
+ charset = get_charset((uint) charset_id, MYF(MY_WME));
ut_ad(charset);
ut_ad(charset->mbmaxlen);
@@ -6825,7 +6840,7 @@ innobase_get_at_most_n_mbchars(
whole string. */
char_length = my_charpos(charset, str,
- str + data_len, n_chars);
+ str + data_len, (int) n_chars);
if (char_length > data_len) {
char_length = data_len;
}
@@ -6948,7 +6963,7 @@ innobase_xa_prepare(
ut_ad(trx->active_trans);
- error = trx_prepare_for_mysql(trx);
+ error = (int) trx_prepare_for_mysql(trx);
} else {
/* We just mark the SQL statement ended and do not do a
transaction prepare */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 4c0f5209af9..90cae3998ed 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -218,7 +218,7 @@ extern long innobase_log_file_size, innobase_log_buffer_size;
extern long innobase_buffer_pool_size, innobase_additional_mem_pool_size;
extern long innobase_buffer_pool_awe_mem_mb;
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
-extern long innobase_force_recovery, innobase_thread_concurrency;
+extern long innobase_force_recovery;
extern long innobase_open_files;
extern char *innobase_data_home_dir, *innobase_data_file_path;
extern char *innobase_log_group_home_dir, *innobase_log_arch_dir;
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 1352fd84d9d..0d9c32adbfa 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -1068,7 +1068,7 @@ bool ha_myisam::check_and_repair(THD *thd)
old_query_length= thd->query_length;
pthread_mutex_lock(&LOCK_thread_count);
thd->query= (char*) table->s->table_name;
- thd->query_length= strlen(table->s->table_name);
+ thd->query_length= (uint32) strlen(table->s->table_name);
pthread_mutex_unlock(&LOCK_thread_count);
if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 0796ded3ac0..5d3f379081c 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -466,7 +466,7 @@ void ha_myisammrg::append_create_info(String *packet)
MYRG_TABLE *open_table,*first;
current_db= table->s->db;
- db_length= strlen(current_db);
+ db_length= (uint) strlen(current_db);
for (first=open_table=file->open_tables ;
open_table != file->end_table ;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index da9f019fb35..1ce0ede7164 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -511,8 +511,13 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans)
DBUG_PRINT("info", ("transformed ndbcluster error %d to mysql error %d",
err.code, res));
if (res == HA_ERR_FOUND_DUPP_KEY)
- m_dupkey= table->s->primary_key;
-
+ {
+ if (m_rows_to_insert == 1)
+ m_dupkey= table->s->primary_key;
+ else
+ // We are batching inserts, offending key is not available
+ m_dupkey= (uint) -1;
+ }
DBUG_RETURN(res);
}
@@ -540,13 +545,12 @@ bool ha_ndbcluster::get_error_message(int error,
}
+#ifndef DBUG_OFF
/*
Check if type is supported by NDB.
- TODO Use this once in open(), not in every operation
-
*/
-static inline bool ndb_supported_type(enum_field_types type)
+static bool ndb_supported_type(enum_field_types type)
{
switch (type) {
case MYSQL_TYPE_TINY:
@@ -581,6 +585,7 @@ static inline bool ndb_supported_type(enum_field_types type)
}
return FALSE;
}
+#endif /* !DBUG_OFF */
/*
@@ -610,15 +615,10 @@ int ha_ndbcluster::set_ndb_key(NdbOperation *ndb_op, Field *field,
pack_len));
DBUG_DUMP("key", (char*)field_ptr, pack_len);
- if (ndb_supported_type(field->type()))
- {
- if (! (field->flags & BLOB_FLAG))
- // Common implementation for most field types
- DBUG_RETURN(ndb_op->equal(fieldnr, (char*) field_ptr, pack_len) != 0);
- }
- // Unhandled field types
- DBUG_PRINT("error", ("Field type %d not supported", field->type()));
- DBUG_RETURN(2);
+ DBUG_ASSERT(ndb_supported_type(field->type()));
+ DBUG_ASSERT(! (field->flags & BLOB_FLAG));
+ // Common implementation for most field types
+ DBUG_RETURN(ndb_op->equal(fieldnr, (char*) field_ptr, pack_len) != 0);
}
@@ -637,7 +637,7 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field,
pack_len, field->is_null()?"Y":"N"));
DBUG_DUMP("value", (char*) field_ptr, pack_len);
- if (ndb_supported_type(field->type()))
+ DBUG_ASSERT(ndb_supported_type(field->type()));
{
// ndb currently does not support size 0
uint32 empty_field;
@@ -715,9 +715,6 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field,
}
DBUG_RETURN(1);
}
- // Unhandled field types
- DBUG_PRINT("error", ("Field type %d not supported", field->type()));
- DBUG_RETURN(2);
}
@@ -812,9 +809,8 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field,
if (field != NULL)
{
- DBUG_ASSERT(buf);
- if (ndb_supported_type(field->type()))
- {
+ DBUG_ASSERT(buf);
+ DBUG_ASSERT(ndb_supported_type(field->type()));
DBUG_ASSERT(field->ptr != NULL);
if (! (field->flags & BLOB_FLAG))
{
@@ -845,10 +841,6 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field,
DBUG_RETURN(ndb_blob->setActiveHook(g_get_ndb_blobs_value, arg) != 0);
}
DBUG_RETURN(1);
- }
- // Unhandled field types
- DBUG_PRINT("error", ("Field type %d not supported", field->type()));
- DBUG_RETURN(2);
}
// Used for hidden key only
@@ -3132,6 +3124,13 @@ double ha_ndbcluster::scan_time()
DBUG_RETURN(res);
}
+/*
+ Convert MySQL table locks into locks supported by Ndb Cluster.
+ Note that MySQL Cluster does currently not support distributed
+ table locks, so to be safe one should set cluster in Single
+ User Mode, before relying on table locks when updating tables
+ from several MySQL servers
+*/
THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd,
THR_LOCK_DATA **to,
@@ -3147,7 +3146,7 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd,
/* Since NDB does not currently have table locks
this is treated as a ordinary lock */
- if ((lock_type >= TL_WRITE_ALLOW_WRITE &&
+ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
lock_type <= TL_WRITE) && !thd->in_lock_tables)
lock_type= TL_WRITE_ALLOW_WRITE;
@@ -4446,7 +4445,7 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
{
const NdbError err= dict->getNdbError();
if (err.code == 709)
- DBUG_RETURN(1);
+ DBUG_RETURN(-1);
ERR_RETURN(err);
}
DBUG_PRINT("info", ("Found table %s", tab->getName()));
@@ -4454,13 +4453,15 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
len= tab->getFrmLength();
if (len == 0 || tab->getFrmData() == NULL)
{
- DBUG_PRINT("No frm data found",
- ("Table is probably created via NdbApi"));
- DBUG_RETURN(2);
+ DBUG_PRINT("error", ("No frm data found."));
+ DBUG_RETURN(1);
}
if (unpackfrm(&data, &len, tab->getFrmData()))
- DBUG_RETURN(3);
+ {
+ DBUG_PRINT("error", ("Could not unpack table"));
+ DBUG_RETURN(1);
+ }
*frmlen= len;
*frmblob= data;
@@ -4473,11 +4474,11 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
*/
-int ndbcluster_table_exists(THD* thd, const char *db, const char *name)
+int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name)
{
const NDBTAB* tab;
Ndb* ndb;
- DBUG_ENTER("ndbcluster_table_exists");
+ DBUG_ENTER("ndbcluster_table_exists_in_engine");
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
if (!(ndb= check_ndb_in_thd(thd)))
@@ -4656,7 +4657,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
DBUG_PRINT("info", ("%s existed on disk", name));
// The .ndb file exists on disk, but it's not in list of tables in ndb
// Verify that handler agrees table is gone.
- if (ndbcluster_table_exists(thd, db, file_name) == 0)
+ if (ndbcluster_table_exists_in_engine(thd, db, file_name) == 0)
{
DBUG_PRINT("info", ("NDB says %s does not exists", file_name));
it.remove();
@@ -4710,7 +4711,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
while ((file_name=it2++))
{
DBUG_PRINT("info", ("Table %s need discovery", file_name));
- if (ha_create_table_from_engine(thd, db, file_name, TRUE) == 0)
+ if (ha_create_table_from_engine(thd, db, file_name) == 0)
files->push_back(thd->strdup(file_name));
}
@@ -6399,6 +6400,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
case(REAL_RESULT):
context->expect_only(Item::REAL_ITEM);
context->expect(Item::DECIMAL_ITEM);
+ context->expect(Item::INT_ITEM);
break;
case(INT_RESULT):
context->expect_only(Item::INT_ITEM);
@@ -6407,6 +6409,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
case(DECIMAL_RESULT):
context->expect_only(Item::DECIMAL_ITEM);
context->expect(Item::REAL_ITEM);
+ context->expect(Item::INT_ITEM);
break;
default:
break;
@@ -6809,6 +6812,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
context->expect_only_field_result(INT_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
}
else
{
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 9ea32e61190..d20fafa458f 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -681,7 +681,8 @@ int ndbcluster_discover(THD* thd, const char* dbname, const char* name,
const void** frmblob, uint* frmlen);
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir, List<char> *files);
-int ndbcluster_table_exists(THD* thd, const char *db, const char *name);
+int ndbcluster_table_exists_in_engine(THD* thd,
+ const char *db, const char *name);
int ndbcluster_drop_database(const char* path);
void ndbcluster_print_error(int error, const NdbOperation *error_op);
diff --git a/sql/handler.cc b/sql/handler.cc
index 1973cd71d46..46a80770024 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -165,12 +165,22 @@ my_bool ha_storage_engine_is_enabled(enum db_type database_type)
/* Use other database handler if databasehandler is not incompiled */
-enum db_type ha_checktype(enum db_type database_type)
+enum db_type ha_checktype(THD *thd, enum db_type database_type,
+ bool no_substitute, bool report_error)
{
- THD *thd;
if (ha_storage_engine_is_enabled(database_type))
return database_type;
+ if (no_substitute)
+ {
+ if (report_error)
+ {
+ const char *engine_name= ha_get_storage_engine(database_type);
+ my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
+ }
+ return DB_TYPE_UNKNOWN;
+ }
+
switch (database_type) {
#ifndef NO_HASH
case DB_TYPE_HASH:
@@ -182,7 +192,6 @@ enum db_type ha_checktype(enum db_type database_type)
break;
}
- thd= current_thd;
return ((enum db_type) thd->variables.table_type != DB_TYPE_UNKNOWN ?
(enum db_type) thd->variables.table_type :
((enum db_type) global_system_variables.table_type !=
@@ -1919,21 +1928,19 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
}
/*
- Try to discover table from engine and
+ Try to discover table from engine and
if found, write the frm file to disk.
-
+
RETURN VALUES:
- 0 : Table existed in engine and created
- on disk if so requested
- 1 : Table does not exist
- >1 : error
+ -1 : Table did not exists
+ 0 : Table created ok
+ > 0 : Error, table existed but could not be created
*/
-int ha_create_table_from_engine(THD* thd,
- const char *db,
- const char *name,
- bool create_if_found)
+int ha_create_table_from_engine(THD* thd,
+ const char *db,
+ const char *name)
{
int error;
const void *frmblob;
@@ -1942,45 +1949,47 @@ int ha_create_table_from_engine(THD* thd,
HA_CREATE_INFO create_info;
TABLE table;
DBUG_ENTER("ha_create_table_from_engine");
- DBUG_PRINT("enter", ("name '%s'.'%s' create_if_found: %d",
- db, name, create_if_found));
+ DBUG_PRINT("enter", ("name '%s'.'%s'",
+ db, name));
bzero((char*) &create_info,sizeof(create_info));
- if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
- DBUG_RETURN(error);
+ if(error= ha_discover(thd, db, name, &frmblob, &frmlen))
+ {
+ // Table could not be discovered and thus not created
+ DBUG_RETURN(error);
+ }
+
/*
- Table exists in handler
- frmblob and frmlen are set
+ Table exists in handler and could be discovered
+ frmblob and frmlen are set, write the frm to disk
*/
- if (create_if_found)
+ (void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS);
+ // Save the frm file
+ if (writefrm(path, frmblob, frmlen))
{
- (void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS);
- // Save the frm file
- if ((error = writefrm(path, frmblob, frmlen)))
- goto err_end;
+ my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_RETURN(2);
+ }
- if (openfrm(thd, path,"",0,(uint) READ_ALL, 0, &table))
- DBUG_RETURN(1);
+ if (openfrm(thd, path,"",0,(uint) READ_ALL, 0, &table))
+ DBUG_RETURN(3);
- update_create_info_from_table(&create_info, &table);
- create_info.table_options|= HA_CREATE_FROM_ENGINE;
+ update_create_info_from_table(&create_info, &table);
+ create_info.table_options|= HA_CREATE_FROM_ENGINE;
- if (lower_case_table_names == 2 &&
- !(table.file->table_flags() & HA_FILE_BASED))
- {
- /* Ensure that handler gets name in lower case */
- my_casedn_str(files_charset_info, path);
- }
-
- error=table.file->create(path,&table,&create_info);
- VOID(closefrm(&table));
+ if (lower_case_table_names == 2 &&
+ !(table.file->table_flags() & HA_FILE_BASED))
+ {
+ /* Ensure that handler gets name in lower case */
+ my_casedn_str(files_charset_info, path);
}
-
-err_end:
+ error=table.file->create(path,&table,&create_info);
+ VOID(closefrm(&table));
my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR));
- DBUG_RETURN(error);
+
+ DBUG_RETURN(error != 0);
}
void st_ha_check_opt::init()
@@ -2083,14 +2092,15 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache,
Try to discover one table from handler(s)
RETURN
- 0 ok. In this case *frmblob and *frmlen are set
- 1 error. frmblob and frmlen may not be set
+ -1 : Table did not exists
+ 0 : OK. In this case *frmblob and *frmlen are set
+ >0 : error. frmblob and frmlen may not be set
*/
int ha_discover(THD *thd, const char *db, const char *name,
const void **frmblob, uint *frmlen)
{
- int error= 1; // Table does not exist in any handler
+ int error= -1; // Table does not exist in any handler
DBUG_ENTER("ha_discover");
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
#ifdef HAVE_NDBCLUSTER_DB
@@ -2122,11 +2132,8 @@ ha_find_files(THD *thd,const char *db,const char *path,
error= ndbcluster_find_files(thd, db, path, wild, dir, files);
#endif
DBUG_RETURN(error);
-
-
}
-#ifdef NOT_YET_USED
/*
Ask handler if the table exists in engine
@@ -2137,20 +2144,19 @@ ha_find_files(THD *thd,const char *db,const char *path,
# Error code
*/
-int ha_table_exists(THD* thd, const char* db, const char* name)
+int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
{
- int error= 2;
- DBUG_ENTER("ha_table_exists");
+ int error= 0;
+ DBUG_ENTER("ha_table_exists_in_engine");
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
#ifdef HAVE_NDBCLUSTER_DB
if (have_ndbcluster == SHOW_OPTION_YES)
- error= ndbcluster_table_exists(thd, db, name);
+ error= ndbcluster_table_exists_in_engine(thd, db, name);
#endif
+ DBUG_PRINT("exit", ("error: %d", error));
DBUG_RETURN(error);
}
-#endif
-
/*
Read the first row of a multi-range set.
diff --git a/sql/handler.h b/sql/handler.h
index 3b0b9afe320..df906e284e7 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -813,7 +813,8 @@ extern ulong total_ha, total_ha_2pc;
enum db_type ha_resolve_by_name(const char *name, uint namelen);
const char *ha_get_storage_engine(enum db_type db_type);
handler *get_new_handler(TABLE *table, enum db_type db_type);
-enum db_type ha_checktype(enum db_type database_type);
+enum db_type ha_checktype(THD *thd, enum db_type database_type,
+ bool no_substitute, bool report_error);
/* basic stuff */
int ha_init(void);
@@ -830,13 +831,12 @@ int ha_delete_table(THD *thd, enum db_type db_type, const char *path,
const char *alias, bool generate_warning);
/* discovery */
-int ha_create_table_from_engine(THD* thd, const char *db, const char *name,
- bool create_if_found);
+int ha_create_table_from_engine(THD* thd, const char *db, const char *name);
int ha_discover(THD* thd, const char* dbname, const char* name,
const void** frmblob, uint* frmlen);
int ha_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir,List<char>* files);
-int ha_table_exists(THD* thd, const char* db, const char* name);
+int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
/* key cache */
int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
diff --git a/sql/item.cc b/sql/item.cc
index 680b771f908..b6f8b7ebc51 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -307,13 +307,14 @@ void *Item::operator new(size_t size, Item *reuse, uint *rsize)
return (void *)reuse;
}
if (rsize)
- (*rsize)= size;
+ (*rsize)= (uint) size;
return (void *)sql_alloc((uint)size);
}
Item::Item():
rsize(0), name(0), orig_name(0), name_length(0), fixed(0),
+ is_autogenerated_name(TRUE),
collation(&my_charset_bin, DERIVATION_COERCIBLE)
{
marker= 0;
@@ -337,6 +338,7 @@ Item::Item():
place == IN_HAVING)
thd->lex->current_select->select_n_having_items++;
}
+ item_flags= 0;
}
/*
@@ -357,7 +359,8 @@ Item::Item(THD *thd, Item *item):
unsigned_flag(item->unsigned_flag),
with_sum_func(item->with_sum_func),
fixed(item->fixed),
- collation(item->collation)
+ collation(item->collation),
+ item_flags(item->item_flags)
{
next= thd->free_list; // Put in free list
thd->free_list= this;
@@ -382,7 +385,7 @@ void Item::print_item_w_name(String *str)
{
THD *thd= current_thd;
str->append(" AS ", 4);
- append_identifier(thd, str, name, strlen(name));
+ append_identifier(thd, str, name, (uint) strlen(name));
}
}
@@ -1132,27 +1135,27 @@ void Item_ident::print(String *str)
if (!table_name || !field_name)
{
const char *nm= field_name ? field_name : name ? name : "tmp_field";
- append_identifier(thd, str, nm, strlen(nm));
+ append_identifier(thd, str, nm, (uint) strlen(nm));
return;
}
if (db_name && db_name[0] && !alias_name_used)
{
- append_identifier(thd, str, d_name, strlen(d_name));
+ append_identifier(thd, str, d_name, (uint) strlen(d_name));
str->append('.');
- append_identifier(thd, str, t_name, strlen(t_name));
+ append_identifier(thd, str, t_name, (uint) strlen(t_name));
str->append('.');
- append_identifier(thd, str, field_name, strlen(field_name));
+ append_identifier(thd, str, field_name, (uint) strlen(field_name));
}
else
{
if (table_name[0])
{
- append_identifier(thd, str, t_name, strlen(t_name));
+ append_identifier(thd, str, t_name, (uint) strlen(t_name));
str->append('.');
- append_identifier(thd, str, field_name, strlen(field_name));
+ append_identifier(thd, str, field_name, (uint) strlen(field_name));
}
else
- append_identifier(thd, str, field_name, strlen(field_name));
+ append_identifier(thd, str, field_name, (uint) strlen(field_name));
}
}
@@ -2179,7 +2182,7 @@ const String *Item_param::query_val_str(String* str) const
ptr+= escape_string_for_mysql(str_value.charset(), ptr, 0,
str_value.ptr(), str_value.length());
*ptr++= '\'';
- str->length(ptr - buf);
+ str->length((uint32) (ptr - buf));
break;
}
case NULL_VALUE:
@@ -3344,6 +3347,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
case MYSQL_TYPE_YEAR:
return new Field_year((char*) 0, max_length, null_ptr, 0, Field::NONE,
name, table);
+ case MYSQL_TYPE_BIT:
+ return new Field_bit_as_char(NULL, max_length, null_ptr, 0, NULL, 0,
+ Field::NONE, name, table);
default:
/* This case should never be chosen */
DBUG_ASSERT(0);
@@ -3570,7 +3576,7 @@ Item *Item_int_with_ref::new_item()
Item_num *Item_uint::neg()
{
- Item_decimal *item= new Item_decimal(value, 0);
+ Item_decimal *item= new Item_decimal(value, 1);
return item->neg();
}
@@ -4360,6 +4366,28 @@ my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
return val;
}
+int Item_ref::save_in_field(Field *to, bool no_conversions)
+{
+ int res;
+ if(result_field){
+ if (result_field->is_null())
+ {
+ null_value= 1;
+ return set_field_to_null_with_conversions(to, no_conversions);
+ }
+ else
+ {
+ to->set_notnull();
+ field_conv(to, result_field);
+ null_value= 0;
+ }
+ return 0;
+ }
+ res= (*ref)->save_in_field(to, no_conversions);
+ null_value= (*ref)->null_value;
+ return res;
+}
+
void Item_ref_null_helper::print(String *str)
{
@@ -4443,6 +4471,7 @@ bool Item_default_value::fix_fields(THD *thd,
struct st_table_list *table_list,
Item **items)
{
+ Item *real_arg;
Item_field *field_arg;
Field *def_field;
DBUG_ASSERT(fixed == 0);
@@ -4454,17 +4483,15 @@ bool Item_default_value::fix_fields(THD *thd,
}
if (!arg->fixed && arg->fix_fields(thd, table_list, &arg))
return TRUE;
-
- if (arg->type() == REF_ITEM)
+
+ real_arg= arg->real_item();
+ if (real_arg->type() != FIELD_ITEM)
{
- Item_ref *ref= (Item_ref *)arg;
- if (ref->ref[0]->type() != FIELD_ITEM)
- {
- return TRUE;
- }
- arg= ref->ref[0];
+ my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name);
+ return TRUE;
}
- field_arg= (Item_field *)arg;
+
+ field_arg= (Item_field *)real_arg;
if (field_arg->field->flags & NO_DEFAULT_VALUE_FLAG)
{
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
@@ -4597,7 +4624,8 @@ void Item_trigger_field::setup_field(THD *thd, TABLE *table)
Try to find field by its name and if it will be found
set field_idx properly.
*/
- (void)find_field_in_real_table(thd, table, field_name, strlen(field_name),
+ (void)find_field_in_real_table(thd, table, field_name,
+ (uint) strlen(field_name),
0, 0, &field_idx);
thd->set_query_id= save_set_query_id;
triggers= table->triggers;
@@ -5387,7 +5415,7 @@ void Item_result_field::cleanup()
** Instantiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<Item>;
template class List_iterator<Item>;
template class List_iterator_fast<Item>;
diff --git a/sql/item.h b/sql/item.h
index 1fe90a41e3a..c8180b4932a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -225,6 +225,11 @@ typedef Item* (Item::*Item_transformer) (byte *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg);
+/*
+ See comments for sql_yacc.yy: insert_update_elem rule
+ */
+#define MY_ITEM_PREFER_1ST_TABLE 1
+
class Item {
Item(const Item &); /* Prevent use of these */
void operator=(Item &);
@@ -269,7 +274,10 @@ public:
my_bool unsigned_flag;
my_bool with_sum_func;
my_bool fixed; /* If item fixed with fix_fields */
+ my_bool is_autogenerated_name; /* indicate was name of this Item
+ autogenerated or set by user */
DTCollation collation;
+ uint8 item_flags; /* Flags on how item should be processed */
// alloc & destruct is done as start of select using sql_alloc
Item();
@@ -288,7 +296,7 @@ public:
name=0;
#endif
} /*lint -e1509 */
- void set_name(const char *str,uint length, CHARSET_INFO *cs);
+ void set_name(const char *str, uint length, CHARSET_INFO *cs);
void rename(char *new_name);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
virtual void cleanup();
@@ -468,6 +476,18 @@ public:
*/
virtual bool const_during_execution() const
{ return (used_tables() & ~PARAM_TABLE_BIT) == 0; }
+ /*
+ This is an essential method for correct functioning of VIEWS.
+ To save a view in an .frm file we need its unequivocal
+ definition in SQL that takes into account sql_mode and
+ environmental settings. Currently such definition is restored
+ by traversing through the parsed tree of a view and
+ print()'ing SQL syntax of every node to a String buffer. This
+ method is used to print the SQL definition of an item. The
+ second use of this method is for EXPLAIN EXTENDED, to print
+ the SQL of a query after all optimizations of the parsed tree
+ have been done.
+ */
virtual void print(String *str_arg) { str_arg->append(full_name()); }
void print_item_w_name(String *);
virtual void update_used_tables() {}
@@ -570,6 +590,11 @@ public:
cleanup();
delete this;
}
+ virtual bool set_flags_processor(byte *args)
+ {
+ this->item_flags|= *((uint8*)args);
+ return false;
+ }
virtual bool is_splocal() { return 0; } /* Needed for error checking */
};
@@ -630,7 +655,7 @@ public:
Item *it= this_item();
if (name)
- it->set_name(name, strlen(name), system_charset_info);
+ it->set_name(name, (uint) strlen(name), system_charset_info);
else
it->set_name(m_name.str, m_name.length, system_charset_info);
it->make_field(field);
@@ -704,10 +729,6 @@ public:
void cleanup();
bool remove_dependence_processor(byte * arg);
void print(String *str);
-
- friend bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
- const char *table_name, List_iterator<Item> *it,
- bool any_privileges, bool allocate_view_names);
};
class Item_equal;
@@ -1158,7 +1179,7 @@ public:
collation.set(cs, dv);
str_value.set_or_copy_aligned(str,length,cs);
max_length= str_value.numchars()*cs->mbmaxlen;
- set_name(name_par,0,cs);
+ set_name(name_par, 0, cs);
decimals=NOT_FIXED_DEC;
// it is constant => can be used without fix_fields (and frequently used)
fixed= 1;
@@ -1335,8 +1356,7 @@ public:
bool send(Protocol *prot, String *tmp);
void make_field(Send_field *field) { (*ref)->make_field(field); }
bool fix_fields(THD *, struct st_table_list *, Item **);
- int save_in_field(Field *field, bool no_conversions)
- { return (*ref)->save_in_field(field, no_conversions); }
+ int save_in_field(Field *field, bool no_conversions);
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
enum_field_types field_type() const { return (*ref)->field_type(); }
@@ -1352,7 +1372,10 @@ public:
{
(*ref)->save_in_field(result_field, no_conversions);
}
- Item *real_item() { return *ref; }
+ Item *real_item()
+ {
+ return (*ref)->real_item();
+ }
bool walk(Item_processor processor, byte *arg)
{ return (*ref)->walk(processor, arg); }
void print(String *str);
@@ -1478,7 +1501,7 @@ public:
str_value.length(), &end_not_used, &err_not_used));
}
longlong val_int()
- {
+ {
int err;
return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),10, (char**) 0,&err);
}
@@ -1493,62 +1516,62 @@ public:
};
-class Item_buff :public Sql_alloc
+class Cached_item :public Sql_alloc
{
public:
my_bool null_value;
- Item_buff() :null_value(0) {}
+ Cached_item() :null_value(0) {}
virtual bool cmp(void)=0;
- virtual ~Item_buff(); /*line -e1509 */
+ virtual ~Cached_item(); /*line -e1509 */
};
-class Item_str_buff :public Item_buff
+class Cached_item_str :public Cached_item
{
Item *item;
String value,tmp_value;
public:
- Item_str_buff(THD *thd, Item *arg);
+ Cached_item_str(THD *thd, Item *arg);
bool cmp(void);
- ~Item_str_buff(); // Deallocate String:s
+ ~Cached_item_str(); // Deallocate String:s
};
-class Item_real_buff :public Item_buff
+class Cached_item_real :public Cached_item
{
Item *item;
double value;
public:
- Item_real_buff(Item *item_par) :item(item_par),value(0.0) {}
+ Cached_item_real(Item *item_par) :item(item_par),value(0.0) {}
bool cmp(void);
};
-class Item_int_buff :public Item_buff
+class Cached_item_int :public Cached_item
{
Item *item;
longlong value;
public:
- Item_int_buff(Item *item_par) :item(item_par),value(0) {}
+ Cached_item_int(Item *item_par) :item(item_par),value(0) {}
bool cmp(void);
};
-class Item_decimal_buff :public Item_buff
+class Cached_item_decimal :public Cached_item
{
Item *item;
my_decimal value;
public:
- Item_decimal_buff(Item *item_par);
+ Cached_item_decimal(Item *item_par);
bool cmp(void);
};
-class Item_field_buff :public Item_buff
+class Cached_item_field :public Cached_item
{
char *buff;
Field *field;
uint length;
public:
- Item_field_buff(Item_field *item)
+ Cached_item_field(Item_field *item)
{
field=item->field;
buff= (char*) sql_calloc(length=field->pack_length());
@@ -1570,7 +1593,7 @@ public:
void print(String *str);
int save_in_field(Field *field_arg, bool no_conversions);
table_map used_tables() const { return (table_map)0L; }
-
+
bool walk(Item_processor processor, byte *args)
{
return arg->walk(processor, args) ||
@@ -1876,7 +1899,7 @@ void mark_select_range_as_dependent(THD *thd,
Field *found_field, Item *found_item,
Item_ident *resolved_item);
-extern Item_buff *new_Item_buff(THD *thd, Item *item);
+extern Cached_item *new_Cached_item(THD *thd, Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b);
extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item);
extern bool field_is_equal_to_item(Field *field,Item *item);
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index 688e4cca846..a67e420170a 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -20,23 +20,23 @@
#include "mysql_priv.h"
/*
-** Create right type of item_buffer for an item
+** Create right type of Cached_item for an item
*/
-Item_buff *new_Item_buff(THD *thd, Item *item)
+Cached_item *new_Cached_item(THD *thd, Item *item)
{
if (item->type() == Item::FIELD_ITEM &&
!(((Item_field *) item)->field->flags & BLOB_FLAG))
- return new Item_field_buff((Item_field *) item);
+ return new Cached_item_field((Item_field *) item);
switch (item->result_type()) {
case STRING_RESULT:
- return new Item_str_buff(thd, (Item_field *) item);
+ return new Cached_item_str(thd, (Item_field *) item);
case INT_RESULT:
- return new Item_int_buff((Item_field *) item);
+ return new Cached_item_int((Item_field *) item);
case REAL_RESULT:
- return new Item_real_buff(item);
+ return new Cached_item_real(item);
case DECIMAL_RESULT:
- return new Item_decimal_buff(item);
+ return new Cached_item_decimal(item);
case ROW_RESULT:
default:
DBUG_ASSERT(0);
@@ -44,24 +44,24 @@ Item_buff *new_Item_buff(THD *thd, Item *item)
}
}
-Item_buff::~Item_buff() {}
+Cached_item::~Cached_item() {}
/*
** Compare with old value and replace value with new value
** Return true if values have changed
*/
-Item_str_buff::Item_str_buff(THD *thd, Item *arg)
+Cached_item_str::Cached_item_str(THD *thd, Item *arg)
:item(arg), value(min(arg->max_length, thd->variables.max_sort_length))
{}
-bool Item_str_buff::cmp(void)
+bool Cached_item_str::cmp(void)
{
String *res;
bool tmp;
- res=item->val_str(&tmp_value);
- res->length(min(res->length(), value.alloced_length()));
+ if ((res=item->val_str(&tmp_value)))
+ res->length(min(res->length(), value.alloced_length()));
if (null_value != item->null_value)
{
if ((null_value= item->null_value))
@@ -77,12 +77,12 @@ bool Item_str_buff::cmp(void)
return tmp;
}
-Item_str_buff::~Item_str_buff()
+Cached_item_str::~Cached_item_str()
{
item=0; // Safety
}
-bool Item_real_buff::cmp(void)
+bool Cached_item_real::cmp(void)
{
double nr= item->val_real();
if (null_value != item->null_value || nr != value)
@@ -94,7 +94,7 @@ bool Item_real_buff::cmp(void)
return FALSE;
}
-bool Item_int_buff::cmp(void)
+bool Cached_item_int::cmp(void)
{
longlong nr=item->val_int();
if (null_value != item->null_value || nr != value)
@@ -107,7 +107,7 @@ bool Item_int_buff::cmp(void)
}
-bool Item_field_buff::cmp(void)
+bool Cached_item_field::cmp(void)
{
bool tmp= field->cmp(buff) != 0; // This is not a blob!
if (tmp)
@@ -121,14 +121,14 @@ bool Item_field_buff::cmp(void)
}
-Item_decimal_buff::Item_decimal_buff(Item *it)
+Cached_item_decimal::Cached_item_decimal(Item *it)
:item(it)
{
my_decimal_set_zero(&value);
}
-bool Item_decimal_buff::cmp()
+bool Cached_item_decimal::cmp()
{
my_decimal tmp;
my_decimal *ptmp= item->val_decimal(&tmp);
@@ -146,7 +146,7 @@ bool Item_decimal_buff::cmp()
** Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
-template class List<Item_buff>;
-template class List_iterator<Item_buff>;
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+template class List<Cached_item>;
+template class List_iterator<Cached_item>;
#endif
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index b5b37efaf07..58a7f3316d7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -238,9 +238,10 @@ void Item_bool_func2::fix_length_and_dec()
return;
}
- if (args[0]->type() == FIELD_ITEM)
+ Item *real_item= args[0]->real_item();
+ if (real_item->type() == FIELD_ITEM)
{
- Field *field=((Item_field*) args[0])->field;
+ Field *field= ((Item_field*) real_item)->field;
if (field->can_be_compared_as_longlong())
{
if (convert_constant_item(thd, field,&args[1]))
@@ -251,9 +252,10 @@ void Item_bool_func2::fix_length_and_dec()
}
}
}
- if (args[1]->type() == FIELD_ITEM /* && !args[1]->const_item() */)
+ real_item= args[1]->real_item();
+ if (real_item->type() == FIELD_ITEM)
{
- Field *field=((Item_field*) args[1])->field;
+ Field *field= ((Item_field*) real_item)->field;
if (field->can_be_compared_as_longlong())
{
if (convert_constant_item(thd, field,&args[0]))
@@ -649,7 +651,7 @@ bool Item_in_optimizer::fix_left(THD *thd,
If it is preparation PS only then we do not know values of parameters =>
cant't get there values and do not need that values.
*/
- if (!thd->only_prepare())
+ if (!thd->current_arena->is_stmt_prepare())
cache->store(args[0]);
if (cache->cols() == 1)
{
@@ -1406,9 +1408,7 @@ Item_func_nullif::val_decimal(my_decimal * decimal_value)
bool
Item_func_nullif::is_null()
{
- if (!cmp.compare())
- return (null_value=1);
- return 0;
+ return (null_value= (!cmp.compare() ? 1 : args[0]->null_value));
}
/*
@@ -1422,6 +1422,8 @@ Item *Item_func_case::find_item(String *str)
my_decimal *first_expr_dec, first_expr_dec_val;
longlong first_expr_int;
double first_expr_real;
+ char buff[MAX_FIELD_WIDTH];
+ String buff_str(buff,sizeof(buff),default_charset());
/* These will be initialized later */
LINT_INIT(first_expr_str);
@@ -1435,7 +1437,7 @@ Item *Item_func_case::find_item(String *str)
{
case STRING_RESULT:
// We can't use 'str' here as this may be overwritten
- if (!(first_expr_str= args[first_expr_num]->val_str(&str_value)))
+ if (!(first_expr_str= args[first_expr_num]->val_str(&buff_str)))
return else_expr_num != -1 ? args[else_expr_num] : 0; // Impossible
break;
case INT_RESULT:
@@ -2794,10 +2796,11 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
if (canDoTurboBM)
{
pattern = first + 1;
- pattern_len = len - 2;
+ pattern_len = (int) len - 2;
DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
- int *suff = (int*) thd->alloc(sizeof(int)*((pattern_len + 1)*2+
- alphabet_size));
+ int *suff = (int*) thd->alloc((int) (sizeof(int)*
+ ((pattern_len + 1)*2+
+ alphabet_size)));
bmGs = suff + pattern_len + 1;
bmBc = bmGs + pattern_len + 1;
turboBM_compute_good_suffix_shifts(suff);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 91defd7f0ee..1dbf28b67cb 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -161,7 +161,7 @@ bool Item_func::agg_arg_charsets(DTCollation &coll,
}
THD *thd= current_thd;
- Item_arena *arena, backup;
+ Query_arena *arena, backup;
bool res= FALSE;
/*
In case we're in statement prepare, create conversion item
@@ -879,11 +879,11 @@ longlong Item_func_numhybrid::val_int()
return (longlong)real_op();
case STRING_RESULT:
{
- char *end_not_used;
int err_not_used;
String *res= str_op(&str_value);
+ char *end= (char*) res->ptr() + res->length();
CHARSET_INFO *cs= str_value.charset();
- return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end_not_used,
+ return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end,
&err_not_used) : 0);
}
default:
@@ -1022,7 +1022,8 @@ longlong Item_func_unsigned::val_int()
String *Item_decimal_typecast::val_str(String *str)
{
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
- my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, &tmp_buf);
+ if (null_value)
+ return NULL;
my_decimal2string(E_DEC_FATAL_ERROR, &tmp_buf, 0, 0, 0, str);
return str;
}
@@ -1032,6 +1033,8 @@ double Item_decimal_typecast::val_real()
{
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
double res;
+ if (null_value)
+ return 0.0;
my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res);
return res;
}
@@ -1041,6 +1044,8 @@ longlong Item_decimal_typecast::val_int()
{
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
longlong res;
+ if (null_value)
+ return 0;
my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res);
return res;
}
@@ -1049,11 +1054,21 @@ longlong Item_decimal_typecast::val_int()
my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec)
{
my_decimal tmp_buf, *tmp= args[0]->val_decimal(&tmp_buf);
+ if ((null_value= args[0]->null_value))
+ return NULL;
my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec);
return dec;
}
+void Item_decimal_typecast::print(String *str)
+{
+ str->append("cast(", 5);
+ args[0]->print(str);
+ str->append(" as decimal)", 12);
+}
+
+
double Item_func_plus::real_op()
{
double value= args[0]->val_real() + args[1]->val_real();
@@ -4104,7 +4119,7 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
return 1; // Same item is same.
/* Check if other type is also a get_user_var() object */
if (item->type() != FUNC_ITEM ||
- ((Item_func*) item)->func_name() != func_name())
+ ((Item_func*) item)->functype() != functype())
return 0;
Item_func_get_user_var *other=(Item_func_get_user_var*) item;
return (name.length == other->name.length &&
@@ -4605,7 +4620,7 @@ Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
if (!(item=var->item(thd, var_type, &null_lex_string)))
return 0; // Impossible
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- item->set_name(item_name, 0, system_charset_info); // Will use original name
+ item->set_name(item_name, 0, system_charset_info); // Will use original name
return item;
}
@@ -4792,42 +4807,36 @@ Item_func_sp::execute(Item **itp)
DBUG_ENTER("Item_func_sp::execute");
THD *thd= current_thd;
ulong old_client_capabilites;
- int res;
+ int res= -1;
bool save_in_sub_stmt= thd->transaction.in_sub_stmt;
+ my_bool nsok;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
st_sp_security_context save_ctx;
#endif
- if (! m_sp)
+ if (! m_sp && ! (m_sp= sp_find_function(thd, m_name, TRUE)))
{
- if (!(m_sp= sp_find_function(thd, m_name, TRUE)))
- {
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
- DBUG_RETURN(-1);
- }
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
+ goto error;
}
old_client_capabilites= thd->client_capabilities;
thd->client_capabilities &= ~CLIENT_MULTI_RESULTS;
#ifndef EMBEDDED_LIBRARY
- my_bool nsok= thd->net.no_send_ok;
+ nsok= thd->net.no_send_ok;
thd->net.no_send_ok= TRUE;
#endif
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_routine_access(thd, EXECUTE_ACL,
m_sp->m_db.str, m_sp->m_name.str, 0, 0))
- DBUG_RETURN(-1);
+ goto error_check;
sp_change_security_context(thd, m_sp, &save_ctx);
if (save_ctx.changed &&
check_routine_access(thd, EXECUTE_ACL,
m_sp->m_db.str, m_sp->m_name.str, 0, 0))
- {
- sp_restore_security_context(thd, m_sp, &save_ctx);
- thd->client_capabilities|= old_client_capabilites & CLIENT_MULTI_RESULTS;
- DBUG_RETURN(-1);
- }
+ goto error_check;
#endif
/*
Like for SPs, we don't binlog the substatements. If the statement which
@@ -4835,6 +4844,7 @@ Item_func_sp::execute(Item **itp)
it's not (e.g. SELECT myfunc()) it won't be binlogged (documented known
problem).
*/
+
tmp_disable_binlog(thd); /* don't binlog the substatements */
thd->transaction.in_sub_stmt= TRUE;
@@ -4849,16 +4859,21 @@ Item_func_sp::execute(Item **itp)
ER_FAILED_ROUTINE_BREAK_BINLOG,
ER(ER_FAILED_ROUTINE_BREAK_BINLOG));
+error_check_ctx:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
sp_restore_security_context(thd, m_sp, &save_ctx);
#endif
+ thd->client_capabilities|= old_client_capabilites & CLIENT_MULTI_RESULTS;
+
+error_check:
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
#endif
thd->client_capabilities|= old_client_capabilites & CLIENT_MULTI_RESULTS;
+error:
DBUG_RETURN(res);
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 1ac1449760f..e0f14ceac75 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -54,7 +54,8 @@ public:
SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN,
NOT_FUNC, NOT_ALL_FUNC,
NOW_FUNC, TRIG_COND_FUNC,
- GUSERVAR_FUNC};
+ GUSERVAR_FUNC, COLLATE_FUNC,
+ EXTRACT_FUNC, CHAR_TYPECAST_FUNC };
enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
OPTIMIZE_EQUAL };
enum Type type() const { return FUNC_ITEM; }
@@ -123,7 +124,17 @@ public:
virtual optimize_type select_optimize() const { return OPTIMIZE_NONE; }
virtual bool have_rev_func() const { return 0; }
virtual Item *key_item() const { return args[0]; }
- virtual const char *func_name() const { return "?"; }
+ /*
+ This method is used for debug purposes to print the name of an
+ item to the debug log. The second use of this method is as
+ a helper function of print(), where it is applicable.
+ To suit both goals it should return a meaningful,
+ distinguishable and sintactically correct string. This method
+ should not be used for runtime type identification, use enum
+ {Sum}Functype and Item_func::functype()/Item_sum::sum_func()
+ instead.
+ */
+ virtual const char *func_name() const= 0;
virtual bool const_item() const { return const_item_cache; }
inline Item **arguments() const { return args; }
void set_arguments(List<Item> &list);
@@ -306,6 +317,8 @@ public:
enum Item_result result_type () const { return DECIMAL_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
void fix_length_and_dec() {};
+ const char *func_name() const { return "decimal_typecast"; }
+ void print(String *);
};
@@ -506,7 +519,7 @@ public:
class Item_func_acos :public Item_dec_func
{
- public:
+public:
Item_func_acos(Item *a) :Item_dec_func(a) {}
double val_real();
const char *func_name() const { return "acos"; }
@@ -514,7 +527,7 @@ class Item_func_acos :public Item_dec_func
class Item_func_asin :public Item_dec_func
{
- public:
+public:
Item_func_asin(Item *a) :Item_dec_func(a) {}
double val_real();
const char *func_name() const { return "asin"; }
@@ -522,7 +535,7 @@ class Item_func_asin :public Item_dec_func
class Item_func_atan :public Item_dec_func
{
- public:
+public:
Item_func_atan(Item *a) :Item_dec_func(a) {}
Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {}
double val_real();
@@ -531,7 +544,7 @@ class Item_func_atan :public Item_dec_func
class Item_func_cos :public Item_dec_func
{
- public:
+public:
Item_func_cos(Item *a) :Item_dec_func(a) {}
double val_real();
const char *func_name() const { return "cos"; }
@@ -539,7 +552,7 @@ class Item_func_cos :public Item_dec_func
class Item_func_sin :public Item_dec_func
{
- public:
+public:
Item_func_sin(Item *a) :Item_dec_func(a) {}
double val_real();
const char *func_name() const { return "sin"; }
@@ -547,7 +560,7 @@ class Item_func_sin :public Item_dec_func
class Item_func_tan :public Item_dec_func
{
- public:
+public:
Item_func_tan(Item *a) :Item_dec_func(a) {}
double val_real();
const char *func_name() const { return "tan"; }
@@ -634,7 +647,7 @@ class Item_func_units :public Item_real_func
{
char *name;
double mul,add;
- public:
+public:
Item_func_units(char *name_arg,Item *a,double mul_arg,double add_arg)
:Item_real_func(a),name(name_arg),mul(mul_arg),add(add_arg) {}
double val_real();
@@ -853,7 +866,7 @@ public:
class Item_func_benchmark :public Item_int_func
{
ulong loop_count;
- public:
+public:
Item_func_benchmark(ulong loop_count_arg,Item *expr)
:Item_int_func(expr), loop_count(loop_count_arg)
{}
@@ -868,7 +881,7 @@ class Item_func_benchmark :public Item_int_func
class Item_udf_func :public Item_func
{
- protected:
+protected:
udf_handler udf;
public:
@@ -1046,7 +1059,7 @@ class Item_func_get_lock :public Item_int_func
class Item_func_release_lock :public Item_int_func
{
String value;
- public:
+public:
Item_func_release_lock(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "release_lock"; }
@@ -1058,7 +1071,7 @@ class Item_func_release_lock :public Item_int_func
class Item_master_pos_wait :public Item_int_func
{
String value;
- public:
+public:
Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {}
Item_master_pos_wait(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
longlong val_int();
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 539bed58e66..06239de1f99 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -363,6 +363,7 @@ String *Item_func_des_encrypt::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
#ifdef HAVE_OPENSSL
+ uint code= ER_WRONG_PARAMETERS_TO_PROCEDURE;
DES_cblock ivec;
struct st_des_keyblock keyblock;
struct st_des_keyschedule keyschedule;
@@ -371,7 +372,7 @@ String *Item_func_des_encrypt::val_str(String *str)
String *res= args[0]->val_str(str);
if ((null_value=args[0]->null_value))
- return 0;
+ goto error;
if ((res_length=res->length()) == 0)
return &my_empty_string;
@@ -419,6 +420,7 @@ String *Item_func_des_encrypt::val_str(String *str)
tail= (8-(res_length) % 8); // 1..8 marking extra length
res_length+=tail;
+ code= ER_OUT_OF_RESOURCES;
if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length+1))
goto error;
(*res)[res_length-1]=tail; // save extra length
@@ -436,6 +438,13 @@ String *Item_func_des_encrypt::val_str(String *str)
return &tmp_value;
error:
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ code, ER(code),
+ "des_encrypt");
+#else
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
+ "des_encrypt","--with-openssl");
#endif /* HAVE_OPENSSL */
null_value=1;
return 0;
@@ -446,6 +455,7 @@ String *Item_func_des_decrypt::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
#ifdef HAVE_OPENSSL
+ uint code= ER_WRONG_PARAMETERS_TO_PROCEDURE;
DES_key_schedule ks1, ks2, ks3;
DES_cblock ivec;
struct st_des_keyblock keyblock;
@@ -454,7 +464,7 @@ String *Item_func_des_decrypt::val_str(String *str)
uint length=res->length(),tail;
if ((null_value=args[0]->null_value))
- return 0;
+ goto error;
length=res->length();
if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128))
return res; // Skip decryption if not encrypted
@@ -485,6 +495,7 @@ String *Item_func_des_decrypt::val_str(String *str)
DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3);
}
+ code= ER_OUT_OF_RESOURCES;
if (tmp_value.alloc(length-1))
goto error;
@@ -498,11 +509,19 @@ String *Item_func_des_decrypt::val_str(String *str)
&ivec, FALSE);
/* Restore old length of key */
if ((tail=(uint) (uchar) tmp_value[length-2]) > 8)
- goto error; // Wrong key
+ goto wrong_key; // Wrong key
tmp_value.length(length-1-tail);
return &tmp_value;
error:
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ code, ER(code),
+ "des_decrypt");
+wrong_key:
+#else
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
+ "des_decrypt","--with-openssl");
#endif /* HAVE_OPENSSL */
null_value=1;
return 0;
@@ -2297,7 +2316,7 @@ bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const
return 0;
Item_func *item_func=(Item_func*) item;
if (arg_count != item_func->arg_count ||
- func_name() != item_func->func_name())
+ functype() != item_func->functype())
return 0;
Item_func_set_collation *item_func_sc=(Item_func_set_collation*) item;
if (collation.collation != item_func_sc->collation.collation)
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 6df90cebdff..c4beb3b08cb 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -322,7 +322,7 @@ public:
Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) {}
String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; }
- const char *func_name() const { return "ecrypt"; }
+ const char *func_name() const { return "encrypt"; }
};
#include "sql_crypt.h"
@@ -573,6 +573,7 @@ public:
max_length=args[0]->max_length;
}
void print(String *str);
+ const char *func_name() const { return "cast_as_binary"; }
};
@@ -648,6 +649,7 @@ public:
void fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "collate"; }
+ enum Functype func_type() const { return COLLATE_FUNC; }
void print(String *str);
Item_field *filed_for_view_update()
{
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 7a72b78b6f4..c7587686ecd 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -194,15 +194,8 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
bool Item_subselect::exec()
{
int res;
- MEM_ROOT *old_root= thd->mem_root;
- /*
- As this is execution, all objects should be allocated through the main
- mem root
- */
- thd->mem_root= &thd->main_mem_root;
res= engine->exec();
- thd->mem_root= old_root;
if (engine_changed)
{
@@ -340,7 +333,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_OK;
SELECT_LEX *select_lex= join->select_lex;
- Item_arena *arena= thd->current_arena;
+ Query_arena *arena= thd->current_arena;
if (!select_lex->master_unit()->first_select()->next_select() &&
!select_lex->table_list.elements &&
@@ -1164,7 +1157,7 @@ Item_in_subselect::select_transformer(JOIN *join)
Item_subselect::trans_res
Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
{
- Item_arena *arena, backup;
+ Query_arena *arena, backup;
SELECT_LEX *current= thd->lex->current_select, *up;
const char *save_where= thd->where;
Item_subselect::trans_res res= RES_ERROR;
@@ -1487,7 +1480,7 @@ int subselect_uniquesubquery_engine::exec()
TABLE *table= tab->table;
for (store_key **copy=tab->ref.key_copy ; *copy ; copy++)
{
- if (tab->ref.key_err= (*copy)->copy())
+ if ((tab->ref.key_err= (*copy)->copy()) & 1)
{
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(1);
@@ -1540,7 +1533,7 @@ int subselect_indexsubquery_engine::exec()
for (store_key **copy=tab->ref.key_copy ; *copy ; copy++)
{
- if (tab->ref.key_err= (*copy)->copy())
+ if ((tab->ref.key_err= (*copy)->copy()) & 1)
{
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(1);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index f7a158ceb5a..76f94801b49 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -86,7 +86,6 @@ void Item_sum::make_field(Send_field *tmp_field)
void Item_sum::print(String *str)
{
str->append(func_name());
- str->append('(');
for (uint i=0 ; i < arg_count ; i++)
{
if (i)
@@ -2425,13 +2424,6 @@ longlong Item_sum_count_distinct::val_int()
}
-void Item_sum_count_distinct::print(String *str)
-{
- str->append("count(distinct ", 15);
- args[0]->print(str);
- str->append(')');
-}
-
/****************************************************************************
** Functions to handle dynamic loadable aggregates
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
@@ -2466,6 +2458,20 @@ void Item_udf_sum::cleanup()
}
+void Item_udf_sum::print(String *str)
+{
+ str->append(func_name());
+ str->append('(');
+ for (uint i=0 ; i < arg_count ; i++)
+ {
+ if (i)
+ str->append(',');
+ args[i]->print(str);
+ }
+ str->append(')');
+}
+
+
Item *Item_sum_udf_float::copy_or_same(THD* thd)
{
return new (thd->mem_root) Item_sum_udf_float(thd, this);
diff --git a/sql/item_sum.h b/sql/item_sum.h
index bb5d31b4b4f..b9a90ee5de5 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -81,7 +81,22 @@ public:
virtual void update_field()=0;
virtual bool keep_field_type(void) const { return 0; }
virtual void fix_length_and_dec() { maybe_null=1; null_value=1; }
- virtual const char *func_name() const { return "?"; }
+ /*
+ This method is used for debug purposes to print the name of an
+ item to the debug log. The second use of this method is as
+ a helper function of print(), where it is applicable.
+ To suit both goals it should return a meaningful,
+ distinguishable and sintactically correct string. This method
+ should not be used for runtime type identification, use enum
+ {Sum}Functype and Item_func::functype()/Item_sum::sum_func()
+ instead.
+
+ NOTE: for Items inherited from Item_sum, func_name() return part of
+ function name till first argument (including '(') to make difference in
+ names for functions with 'distinct' clause and without 'distinct' and
+ also to make printing of items inherited from Item_sum uniform.
+ */
+ virtual const char *func_name() const= 0;
virtual Item *result_item(Field *field)
{ return new Item_field(field);}
table_map used_tables() const { return ~(table_map) 0; } /* Not used */
@@ -159,7 +174,7 @@ public:
void reset_field();
void update_field();
void no_rows_in_result() {}
- const char *func_name() const { return "sum"; }
+ const char *func_name() const { return "sum("; }
Item *copy_or_same(THD* thd);
};
@@ -200,7 +215,6 @@ public:
enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; }
void reset_field() {} // not used
void update_field() {} // not used
- const char *func_name() const { return "sum_distinct"; }
virtual void no_rows_in_result() {}
void fix_length_and_dec();
enum Item_result result_type () const { return val.traits->type(); }
@@ -224,7 +238,7 @@ public:
Item_sum_sum_distinct(Item *item_arg) :Item_sum_distinct(item_arg) {}
enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; }
- const char *func_name() const { return "sum_distinct"; }
+ const char *func_name() const { return "sum(distinct "; }
Item *copy_or_same(THD* thd) { return new Item_sum_sum_distinct(thd, this); }
};
@@ -243,7 +257,7 @@ public:
void fix_length_and_dec();
virtual void calculate_val_and_count();
enum Sumfunctype sum_func () const { return AVG_DISTINCT_FUNC; }
- const char *func_name() const { return "avg_distinct"; }
+ const char *func_name() const { return "avg(distinct "; }
Item *copy_or_same(THD* thd) { return new Item_sum_avg_distinct(thd, this); }
};
@@ -272,7 +286,7 @@ class Item_sum_count :public Item_sum_int
void reset_field();
void cleanup();
void update_field();
- const char *func_name() const { return "count"; }
+ const char *func_name() const { return "count("; }
Item *copy_or_same(THD* thd);
};
@@ -326,12 +340,11 @@ public:
longlong val_int();
void reset_field() { return ;} // Never called
void update_field() { return ; } // Never called
- const char *func_name() const { return "count_distinct"; }
+ const char *func_name() const { return "count(distinct "; }
bool setup(THD *thd);
void make_unique();
Item *copy_or_same(THD* thd);
void no_rows_in_result() {}
- void print(String *str);
};
@@ -389,7 +402,7 @@ public:
Item *result_item(Field *field)
{ return new Item_avg_field(hybrid_type, this); }
void no_rows_in_result() {}
- const char *func_name() const { return "avg"; }
+ const char *func_name() const { return "avg("; }
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
};
@@ -466,7 +479,7 @@ public:
Item *result_item(Field *field)
{ return new Item_variance_field(this); }
void no_rows_in_result() {}
- const char *func_name() const { return "variance"; }
+ const char *func_name() const { return "variance("; }
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
enum Item_result result_type () const { return hybrid_type; }
@@ -501,7 +514,7 @@ class Item_sum_std :public Item_sum_variance
double val_real();
Item *result_item(Field *field)
{ return new Item_std_field(this); }
- const char *func_name() const { return "std"; }
+ const char *func_name() const { return "std("; }
Item *copy_or_same(THD* thd);
enum Item_result result_type () const { return REAL_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;}
@@ -565,7 +578,7 @@ public:
enum Sumfunctype sum_func () const {return MIN_FUNC;}
bool add();
- const char *func_name() const { return "min"; }
+ const char *func_name() const { return "min("; }
Item *copy_or_same(THD* thd);
};
@@ -578,7 +591,7 @@ public:
enum Sumfunctype sum_func () const {return MAX_FUNC;}
bool add();
- const char *func_name() const { return "max"; }
+ const char *func_name() const { return "max("; }
Item *copy_or_same(THD* thd);
};
@@ -609,7 +622,7 @@ public:
Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {}
bool add();
- const char *func_name() const { return "bit_or"; }
+ const char *func_name() const { return "bit_or("; }
Item *copy_or_same(THD* thd);
};
@@ -620,7 +633,7 @@ class Item_sum_and :public Item_sum_bit
Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {}
Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {}
bool add();
- const char *func_name() const { return "bit_and"; }
+ const char *func_name() const { return "bit_and("; }
Item *copy_or_same(THD* thd);
};
@@ -630,7 +643,7 @@ class Item_sum_xor :public Item_sum_bit
Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {}
bool add();
- const char *func_name() const { return "bit_xor"; }
+ const char *func_name() const { return "bit_xor("; }
Item *copy_or_same(THD* thd);
};
@@ -668,6 +681,7 @@ public:
void reset_field() {};
void update_field() {};
void cleanup();
+ void print(String *str);
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 564c5e4b9cc..19386c15835 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2158,7 +2158,7 @@ bool Item_extract::eq(const Item *item, bool binary_cmp) const
if (this == item)
return 1;
if (item->type() != FUNC_ITEM ||
- func_name() != ((Item_func*)item)->func_name())
+ functype() != ((Item_func*)item)->functype())
return 0;
Item_extract* ie= (Item_extract*)item;
@@ -2176,7 +2176,7 @@ bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const
if (this == item)
return 1;
if (item->type() != FUNC_ITEM ||
- func_name() != ((Item_func*)item)->func_name())
+ functype() != ((Item_func*)item)->functype())
return 0;
Item_char_typecast *cast= (Item_char_typecast*)item;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index c8fb2b39836..a6dd9f7da91 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -503,7 +503,8 @@ public:
Item_func_date_format(Item *a,Item *b,bool is_time_format_arg)
:Item_str_func(a,b),is_time_format(is_time_format_arg) {}
String *val_str(String *str);
- const char *func_name() const { return "date_format"; }
+ const char *func_name() const
+ { return is_time_format ? "time_format" : "date_format"; }
void fix_length_and_dec();
uint format_length(const String *format);
};
@@ -637,6 +638,7 @@ class Item_extract :public Item_int_func
Item_extract(interval_type type_arg, Item *a)
:Item_int_func(a), int_type(type_arg) {}
longlong val_int();
+ enum Functype functype() const { return EXTRACT_FUNC; }
const char *func_name() const { return "extract"; }
void fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const;
@@ -689,6 +691,7 @@ class Item_char_typecast :public Item_typecast
public:
Item_char_typecast(Item *a, int length_arg, CHARSET_INFO *cs_arg)
:Item_typecast(a), cast_length(length_arg), cast_cs(cs_arg) {}
+ enum Functype functype() const { return CHAR_TYPECAST_FUNC; }
bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "cast_as_char"; }
const char* cast_type() const { return "char"; };
@@ -790,6 +793,7 @@ public:
return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin));
}
void print(String *str);
+ const char *func_name() const { return "add_time"; }
};
class Item_func_timediff :public Item_str_func
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index 14b2e8d53bb..e95aa35101e 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -30,6 +30,7 @@ public:
double val_real() { 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); }
+ const char *func_name() const { return "unique_users"; }
};
@@ -58,4 +59,5 @@ public:
}
void print(String *str) { str->append("0.0", 3); }
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
+ const char *func_name() const { return "sum_unique_users"; }
};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index b6f4b963393..805af08b76a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -325,6 +325,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MODE_TRADITIONAL (MODE_ERROR_FOR_DIVISION_BY_ZERO*2)
#define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2)
#define MODE_HIGH_NOT_PRECEDENCE (MODE_NO_AUTO_CREATE_USER*2)
+#define MODE_NO_ENGINE_SUBSTITUTION (MODE_HIGH_NOT_PRECEDENCE*2)
/*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
use strictly more than 64 bits by adding one more define above, you should
@@ -559,8 +560,6 @@ struct Query_cache_query_flags
#define query_cache_invalidate_by_MyISAM_filename_ref NULL
#endif /*HAVE_QUERY_CACHE*/
-#define prepare_execute(A) ((A)->command == COM_EXECUTE)
-
bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
@@ -599,6 +598,7 @@ bool mysql_execute_command(THD *thd);
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length);
+void log_slow_statement(THD *thd);
bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
bool table_cache_init(void);
@@ -667,6 +667,7 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field,
bool group, bool modify_item,
+ bool table_cant_handle_bit_fields,
uint convert_blob_length);
void sp_prepare_create_field(THD *thd, create_field *sql_field);
int prepare_create_field(create_field *sql_field,
@@ -841,7 +842,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
void mysql_stmt_execute(THD *thd, char *packet, uint packet_length);
void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name);
void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length);
-void mysql_stmt_free(THD *thd, char *packet);
+void mysql_stmt_close(THD *thd, char *packet);
void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
void reinit_stmt_before_use(THD *thd, LEX *lex);
@@ -894,8 +895,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list);
bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
- List_iterator<Item> *it, bool any_privileges,
- bool allocate_view_names);
+ List_iterator<Item> *it, bool any_privileges);
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
TABLE_LIST **leaves, bool select_insert);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
@@ -1116,6 +1116,7 @@ extern my_bool opt_slave_compressed_protocol, use_temp_pool;
extern my_bool opt_readonly, lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
+extern my_bool opt_log_slow_admin_statements;
extern my_bool sp_automatic_privileges, opt_noacl;
extern my_bool opt_old_style_user_limits, trust_routine_creators;
extern uint opt_crash_binlog_innodb;
@@ -1230,7 +1231,7 @@ int openfrm(THD *thd, const char *name,const char *alias,uint filestat,
int readfrm(const char *name, const void** data, uint* length);
int writefrm(const char* name, const void* data, uint len);
int closefrm(TABLE *table);
-db_type get_table_type(const char *name);
+db_type get_table_type(THD *thd, const char *name);
int read_string(File file, gptr *to, uint length);
void free_blobs(TABLE *table);
int set_zone(int nr,int min_zone,int max_zone);
@@ -1287,7 +1288,7 @@ ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
const char *newname);
ulong next_io_size(ulong pos);
void append_unescaped(String *res, const char *pos, uint length);
-int create_frm(char *name,uint reclength,uchar *fileinfo,
+int create_frm(THD *thd, char *name,uint reclength,uchar *fileinfo,
HA_CREATE_INFO *create_info, uint keys);
void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
int rename_file_ext(const char * from,const char * to,const char * ext);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f9bf5a1a7c3..bc4cc81506e 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -140,6 +140,7 @@ int deny_severity = LOG_WARNING;
#define zVOLSTATE_DEACTIVE 2
#define zVOLSTATE_MAINTENANCE 3
+#include <nks/netware.h>
#include <nks/vm.h>
#include <library.h>
#include <monitor.h>
@@ -229,6 +230,7 @@ static const char *sql_mode_names[] =
"NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", "STRICT_ALL_TABLES",
"NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO",
"TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
+ "NO_ENGINE_SUBSTITUTION",
NullS
};
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
@@ -326,6 +328,7 @@ ulong opt_ndb_nodeid;
my_bool opt_readonly, use_temp_pool, relay_log_purge;
my_bool opt_sync_frm, opt_allow_suspicious_udfs;
my_bool opt_secure_auth= 0;
+my_bool opt_log_slow_admin_statements= 0;
my_bool lower_case_file_system= 0;
my_bool opt_large_pages= 0;
uint opt_large_page_size= 0;
@@ -1276,19 +1279,6 @@ static void server_init(void)
int arg=1;
DBUG_ENTER("server_init");
-#ifdef __WIN__
- if (!opt_disable_networking)
- {
- WSADATA WsaData;
- if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
- {
- /* errors are not read yet, so we use test here */
- my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0));
- unireg_abort(1);
- }
- }
-#endif /* __WIN__ */
-
set_ports();
if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
@@ -3015,6 +3005,21 @@ int main(int argc, char **argv)
}
#endif
+#ifdef __WIN__
+/* Before performing any socket operation (like retrieving hostname */
+/* in init_common_variables we have to call WSAStartup */
+ if (!opt_disable_networking)
+ {
+ WSADATA WsaData;
+ if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
+ {
+ /* errors are not read yet, so we use test here */
+ my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0));
+ unireg_abort(1);
+ }
+ }
+#endif /* __WIN__ */
+
if (init_common_variables(MYSQL_CONFIG_NAME,
argc, argv, load_default_groups))
unireg_abort(1); // Will do exit
@@ -4331,7 +4336,8 @@ enum options_mysqld
OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
OPT_ENABLE_LARGE_PAGES,
OPT_TIMED_MUTEXES,
- OPT_OLD_STYLE_USER_LIMITS
+ OPT_OLD_STYLE_USER_LIMITS,
+ OPT_LOG_SLOW_ADMIN_STATEMENTS
};
@@ -4453,7 +4459,7 @@ Disable with --skip-bdb (will save memory).",
(gptr*) &default_collation_name, (gptr*) &default_collation_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{"default-storage-engine", OPT_STORAGE_ENGINE,
- "Set the default storage engine (table tyoe) for tables.", 0, 0,
+ "Set the default storage engine (table type) for tables.", 0, 0,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"default-table-type", OPT_STORAGE_ENGINE,
"(deprecated) Use --default-storage-engine.", 0, 0,
@@ -4656,7 +4662,7 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
"Log some extra information to update log. Please note that this option is deprecated; see --log-short-format option.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"log-queries-not-using-indexes", OPT_LOG_QUERIES_NOT_USING_INDEXES,
- "Log queries that are executed without benefit of any index.",
+ "Log queries that are executed without benefit of any index to the slow log if it is open.",
(gptr*) &opt_log_queries_not_using_indexes, (gptr*) &opt_log_queries_not_using_indexes,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"log-short-format", OPT_SHORT_LOG_FORMAT,
@@ -4667,8 +4673,13 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
"Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves.",
(gptr*) &opt_log_slave_updates, (gptr*) &opt_log_slave_updates, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"log-slow-admin-statements", OPT_LOG_SLOW_ADMIN_STATEMENTS,
+ "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open.",
+ (gptr*) &opt_log_slow_admin_statements,
+ (gptr*) &opt_log_slow_admin_statements,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"log-slow-queries", OPT_SLOW_QUERY_LOG,
- "Log slow queries to this log file. Defaults logging to hostname-slow.log file.",
+ "Log slow queries to this log file. Defaults logging to hostname-slow.log file. Must be enabled to activate other slow log options.",
(gptr*) &opt_slow_logname, (gptr*) &opt_slow_logname, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"log-tc", OPT_LOG_TC,
@@ -5228,7 +5239,7 @@ log and this option does nothing anymore.",
{"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY,
"Helps in performance tuning in heavily concurrent environments.",
(gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency,
- 0, GET_LONG, REQUIRED_ARG, 8, 1, 1000, 0, 1, 0},
+ 0, GET_LONG, REQUIRED_ARG, 20, 1, 1000, 0, 1, 0},
{"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY,
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0"
" disable a sleep",
@@ -5716,6 +5727,12 @@ struct show_var_st status_vars[]= {
{"Com_show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
{"Com_slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
{"Com_slave_stop", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS},
+ {"Com_stmt_prepare", (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS},
+ {"Com_stmt_execute", (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS},
+ {"Com_stmt_fetch", (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS},
+ {"Com_stmt_send_long_data", (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS},
+ {"Com_stmt_reset", (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS},
+ {"Com_stmt_close", (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS},
{"Com_truncate", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
{"Com_unlock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
{"Com_update", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS},
@@ -6343,6 +6360,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case (int) OPT_SLOW_QUERY_LOG:
opt_slow_log=1;
break;
+ case (int) OPT_LOG_SLOW_ADMIN_STATEMENTS:
+ opt_log_slow_admin_statements= 1;
+ break;
case (int) OPT_SKIP_NEW:
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
@@ -6731,6 +6751,9 @@ static void get_options(int argc,char **argv)
if (opt_bdb)
sql_print_warning("this binary does not contain BDB storage engine");
#endif
+ if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes) &&
+ !opt_slow_log)
+ sql_print_warning("options --log-slow-admin-statements and --log-queries-not-using-indexes have no effect if --log-slow-queries is not set");
/*
Check that the default storage engine is actually available.
@@ -7051,7 +7074,7 @@ static void create_pid_file()
Instantiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
/* Used templates */
template class I_List<THD>;
template class I_List_iterator<THD>;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index b3301d17655..3226dc9607b 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -325,7 +325,7 @@ typedef struct st_qsel_param {
TABLE *table;
KEY_PART *key_parts,*key_parts_end;
KEY_PART *key[MAX_KEY]; /* First key parts of keys used in the query */
- MEM_ROOT *mem_root;
+ MEM_ROOT *mem_root, *old_root;
table_map prev_tables,read_tables,current_table;
uint baseflag, max_key_part, range_count;
@@ -1665,7 +1665,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
keys_to_use.intersect(head->keys_in_use_for_query);
if (!keys_to_use.is_clear_all())
{
- MEM_ROOT *old_root,alloc;
+ MEM_ROOT alloc;
SEL_TREE *tree= NULL;
KEY_PART *key_parts;
KEY *key_info;
@@ -1680,6 +1680,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
param.table=head;
param.keys=0;
param.mem_root= &alloc;
+ param.old_root= thd->mem_root;
param.needed_reg= &needed_reg;
param.imerge_cost_buff_size= 0;
@@ -1695,7 +1696,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_RETURN(0); // Can't use range
}
key_parts= param.key_parts;
- old_root= thd->mem_root;
thd->mem_root= &alloc;
/*
@@ -1845,7 +1845,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
}
}
- thd->mem_root= old_root;
+ thd->mem_root= param.old_root;
/* If we got a read plan, create a quick select from it. */
if (best_trp)
@@ -1860,7 +1860,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
free_mem:
free_root(&alloc,MYF(0)); // Return memory & allocator
- thd->mem_root= old_root;
+ thd->mem_root= param.old_root;
thd->no_errors=0;
}
@@ -2593,12 +2593,12 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
{
tuple_arg= scan->sel_arg;
/* Here we use the length of the first key part */
- tuple_arg->store_min(key_part->length, &key_ptr, 0);
+ tuple_arg->store_min(key_part->store_length, &key_ptr, 0);
}
while (tuple_arg->next_key_part != sel_arg)
{
tuple_arg= tuple_arg->next_key_part;
- tuple_arg->store_min(key_part[tuple_arg->part].length, &key_ptr, 0);
+ tuple_arg->store_min(key_part[tuple_arg->part].store_length, &key_ptr, 0);
}
min_range.length= max_range.length= ((char*) key_ptr - (char*) key_val);
records= (info->param->table->file->
@@ -3581,15 +3581,16 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
DBUG_RETURN(ftree);
}
default:
- if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
+ if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
{
- field_item= (Item_field*) (cond_func->arguments()[0]);
+ field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
value= cond_func->arg_count > 1 ? cond_func->arguments()[1] : 0;
}
else if (cond_func->have_rev_func() &&
- cond_func->arguments()[1]->type() == Item::FIELD_ITEM)
+ cond_func->arguments()[1]->real_item()->type() ==
+ Item::FIELD_ITEM)
{
- field_item= (Item_field*) (cond_func->arguments()[1]);
+ field_item= (Item_field*) (cond_func->arguments()[1]->real_item());
value= cond_func->arguments()[0];
}
else
@@ -3610,7 +3611,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
for (uint i= 0; i < cond_func->arg_count; i++)
{
- Item *arg= cond_func->arguments()[i];
+ Item *arg= cond_func->arguments()[i]->real_item();
if (arg != field_item)
ref_tables|= arg->used_tables();
}
@@ -3695,24 +3696,38 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
{
uint maybe_null=(uint) field->real_maybe_null();
bool optimize_range;
- SEL_ARG *tree;
+ SEL_ARG *tree= 0;
+ MEM_ROOT *alloc= param->mem_root;
char *str;
DBUG_ENTER("get_mm_leaf");
+ /*
+ We need to restore the runtime mem_root of the thread in this
+ function because it evaluates the value of its argument, while
+ the argument can be any, e.g. a subselect. The subselect
+ items, in turn, assume that all the memory allocated during
+ the evaluation has the same life span as the item itself.
+ TODO: opt_range.cc should not reset thd->mem_root at all.
+ */
+ param->thd->mem_root= param->old_root;
if (!value) // IS NULL or IS NOT NULL
{
if (field->table->maybe_null) // Can't use a key on this
- DBUG_RETURN(0);
+ goto end;
if (!maybe_null) // Not null field
- DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0);
- if (!(tree=new SEL_ARG(field,is_null_string,is_null_string)))
- DBUG_RETURN(0); // out of memory
+ {
+ if (type == Item_func::ISNULL_FUNC)
+ tree= &null_element;
+ goto end;
+ }
+ if (!(tree= new (alloc) SEL_ARG(field,is_null_string,is_null_string)))
+ goto end; // out of memory
if (type == Item_func::ISNOTNULL_FUNC)
{
tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */
tree->max_flag=NO_MAX_RANGE;
}
- DBUG_RETURN(tree);
+ goto end;
}
/*
@@ -3732,7 +3747,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
key_part->image_type == Field::itRAW &&
((Field_str*)field)->charset() != conf_func->compare_collation() &&
!(conf_func->compare_collation()->state & MY_CS_BINSORT))
- DBUG_RETURN(0);
+ goto end;
optimize_range= field->optimize_range(param->real_keynr[key_part->key],
key_part->part);
@@ -3746,9 +3761,12 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
uint field_length= field->pack_length()+maybe_null;
if (!optimize_range)
- DBUG_RETURN(0); // Can't optimize this
+ goto end;
if (!(res= value->val_str(&tmp)))
- DBUG_RETURN(&null_element);
+ {
+ tree= &null_element;
+ goto end;
+ }
/*
TODO:
@@ -3761,7 +3779,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
res= &tmp;
}
if (field->cmp_type() != STRING_RESULT)
- DBUG_RETURN(0); // Can only optimize strings
+ goto end; // Can only optimize strings
offset=maybe_null;
length=key_part->store_length;
@@ -3786,8 +3804,8 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
field_length= length;
}
length+=offset;
- if (!(min_str= (char*) alloc_root(param->mem_root, length*2)))
- DBUG_RETURN(0);
+ if (!(min_str= (char*) alloc_root(alloc, length*2)))
+ goto end;
max_str=min_str+length;
if (maybe_null)
@@ -3802,20 +3820,21 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
min_str+offset, max_str+offset,
&min_length, &max_length);
if (like_error) // Can't optimize with LIKE
- DBUG_RETURN(0);
+ goto end;
if (offset != maybe_null) // BLOB or VARCHAR
{
int2store(min_str+maybe_null,min_length);
int2store(max_str+maybe_null,max_length);
}
- DBUG_RETURN(new SEL_ARG(field,min_str,max_str));
+ tree= new (alloc) SEL_ARG(field, min_str, max_str);
+ goto end;
}
if (!optimize_range &&
type != Item_func::EQ_FUNC &&
type != Item_func::EQUAL_FUNC)
- DBUG_RETURN(0); // Can't optimize this
+ goto end; // Can't optimize this
/*
We can't always use indexes when comparing a string index to a number
@@ -3824,21 +3843,53 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
if (field->result_type() == STRING_RESULT &&
value->result_type() != STRING_RESULT &&
field->cmp_type() != value->result_type())
- DBUG_RETURN(0);
+ goto end;
if (value->save_in_field_no_warnings(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
+ tree= &null_element; // cmp with NULL is never TRUE
+ goto end;
}
- str= (char*) alloc_root(param->mem_root, key_part->store_length+1);
+ str= (char*) alloc_root(alloc, key_part->store_length+1);
if (!str)
- DBUG_RETURN(0);
+ goto end;
if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null
field->get_key_image(str+maybe_null, key_part->length, key_part->image_type);
- if (!(tree=new SEL_ARG(field,str,str)))
- DBUG_RETURN(0); // out of memory
+ if (!(tree= new (alloc) SEL_ARG(field, str, str)))
+ goto end; // out of memory
+
+ /*
+ Check if we are comparing an UNSIGNED integer with a negative constant.
+ In this case we know that:
+ (a) (unsigned_int [< | <=] negative_constant) == FALSE
+ (b) (unsigned_int [> | >=] negative_constant) == TRUE
+ In case (a) the condition is false for all values, and in case (b) it
+ is true for all values, so we can avoid unnecessary retrieval and condition
+ testing, and we also get correct comparison of unsinged integers with
+ negative integers (which otherwise fails because at query execution time
+ negative integers are cast to unsigned if compared with unsigned).
+ */
+ if (field->result_type() == INT_RESULT &&
+ value->result_type() == INT_RESULT &&
+ ((Field_num*)field)->unsigned_flag && !((Item_int*)value)->unsigned_flag)
+ {
+ longlong item_val= value->val_int();
+ if (item_val < 0)
+ {
+ if (type == Item_func::LT_FUNC || type == Item_func::LE_FUNC)
+ {
+ tree->type= SEL_ARG::IMPOSSIBLE;
+ goto end;
+ }
+ if (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC)
+ {
+ tree= 0;
+ goto end;
+ }
+ }
+ }
switch (type) {
case Item_func::LT_FUNC:
@@ -3899,6 +3950,9 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
default:
break;
}
+
+end:
+ param->thd->mem_root= alloc;
DBUG_RETURN(tree);
}
@@ -5992,7 +6046,10 @@ int QUICK_RANGE_SELECT::reset()
next=0;
range= NULL;
cur_range= (QUICK_RANGE**) ranges.buffer;
-
+
+ if (file->inited == handler::NONE && (error= file->ha_index_init(index)))
+ DBUG_RETURN(error);
+
/* Do not allocate the buffers twice. */
if (multi_range_length)
{
@@ -7612,8 +7669,8 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
*records= num_groups;
DBUG_PRINT("info",
- ("records=%u, keys/block=%u, keys/group=%u, records=%u, blocks=%u",
- table_records, keys_per_block, keys_per_group, records,
+ ("table rows=%u, keys/block=%u, keys/group=%u, result rows=%u, blocks=%u",
+ table_records, keys_per_block, keys_per_group, *records,
num_blocks));
DBUG_VOID_RETURN;
}
@@ -8120,6 +8177,15 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next()
DBUG_ASSERT((have_max && !have_min) ||
(have_max && have_min && (max_res == 0)));
}
+ /*
+ If this is a just a GROUP BY or DISTINCT without MIN or MAX and there
+ are equality predicates for the key parts after the group, find the
+ first sub-group with the extended prefix.
+ */
+ if (!have_min && !have_max && key_infix_len > 0)
+ result= file->index_read(record, group_prefix, real_prefix_len,
+ HA_READ_KEY_EXACT);
+
result= have_min ? min_res : have_max ? max_res : result;
}
while (result == HA_ERR_KEY_NOT_FOUND && is_last_prefix != 0);
@@ -8146,9 +8212,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next()
QUICK_GROUP_MIN_MAX_SELECT::next_min()
DESCRIPTION
- Load the prefix of the next group into group_prefix and find the minimal
- key within this group such that the key satisfies the query conditions and
- NULL semantics. The found key is loaded into this->record.
+ Find the minimal key within this group such that the key satisfies the query
+ conditions and NULL semantics. The found key is loaded into this->record.
IMPLEMENTATION
Depending on the values of min_max_ranges.elements, key_infix_len, and
@@ -8232,9 +8297,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
QUICK_GROUP_MIN_MAX_SELECT::next_max()
DESCRIPTION
- If there was no previous next_min call to determine the next group prefix,
- then load the next prefix into group_prefix, then lookup the maximal key of
- the group, and store it into this->record.
+ Lookup the maximal key of the group, and store it into this->record.
RETURN
0 on success
@@ -8912,7 +8975,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose)
** Instantiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<QUICK_RANGE>;
template class List_iterator<QUICK_RANGE>;
#endif
diff --git a/sql/password.c b/sql/password.c
index 79675ade30b..60cc0ac0c97 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -146,7 +146,7 @@ void hash_password(ulong *result, const char *password, uint password_len)
void make_scrambled_password_323(char *to, const char *password)
{
ulong hash_res[2];
- hash_password(hash_res, password, strlen(password));
+ hash_password(hash_res, password, (uint) strlen(password));
sprintf(to, "%08lx%08lx", hash_res[0], hash_res[1]);
}
@@ -172,7 +172,7 @@ void scramble_323(char *to, const char *message, const char *password)
{
char extra, *to_start=to;
const char *message_end= message + SCRAMBLE_LENGTH_323;
- hash_password(hash_pass,password, strlen(password));
+ hash_password(hash_pass,password, (uint) strlen(password));
hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
hash_pass[1] ^ hash_message[1]);
@@ -394,7 +394,7 @@ make_scrambled_password(char *to, const char *password)
sha1_reset(&sha1_context);
/* stage 1: hash password */
- sha1_input(&sha1_context, (uint8 *) password, strlen(password));
+ sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
sha1_result(&sha1_context, (uint8 *) to);
/* stage 2: hash stage1 output */
sha1_reset(&sha1_context);
@@ -433,7 +433,7 @@ scramble(char *to, const char *message, const char *password)
sha1_reset(&sha1_context);
/* stage 1: hash password */
- sha1_input(&sha1_context, (uint8 *) password, strlen(password));
+ sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
sha1_result(&sha1_context, hash_stage1);
/* stage 2: hash stage 1; note that hash_stage2 is stored in the database */
sha1_reset(&sha1_context);
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 57922cdc677..1c399a89a99 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -294,7 +294,12 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
DBUG_ENTER("send_ok");
if (net->no_send_ok || !net->vio) // hack for re-parsing queries
+ {
+ DBUG_PRINT("info", ("no send ok: %s, vio present: %s",
+ (net->no_send_ok ? "YES" : "NO"),
+ (net->vio ? "YES" : "NO")));
DBUG_VOID_RETURN;
+ }
buff[0]=0; // No fields
pos=net_store_length(buff+1,(ulonglong) affected_rows);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index b22c0924de1..1c0de702e4e 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -3131,7 +3131,7 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
if (!(res=var->value->val_str(&str)) ||
!(var->save_result.ulong_value=
(ulong) (db_type= ha_resolve_by_name(res->ptr(), res->length()))) ||
- ha_checktype(db_type) != db_type)
+ ha_checktype(thd, db_type, 1, 0) != db_type)
{
value= res ? res->c_ptr() : "NULL";
goto err;
@@ -3406,7 +3406,7 @@ bool process_key_caches(int (* func) (const char *name, KEY_CACHE *))
Used templates
****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<set_var_base>;
template class List_iterator_fast<set_var_base>;
template class I_List_iterator<NAMED_LIST>;
diff --git a/sql/set_var.h b/sql/set_var.h
index 56690c46131..a6532323b34 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -786,7 +786,8 @@ public:
if (value_arg && value_arg->type() == Item::FIELD_ITEM)
{
Item_field *item= (Item_field*) value_arg;
- if (!(value=new Item_string(item->field_name, strlen(item->field_name),
+ if (!(value=new Item_string(item->field_name,
+ (uint) strlen(item->field_name),
item->collation.collation)))
value=value_arg; /* Give error message later */
}
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index a020cadc084..7ae5130764f 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5021,7 +5021,7 @@ ER_NON_UPDATABLE_TABLE
por "A tabela destino %-.100s do %s não é atualizável"
rus "ôÁÂÌÉÃÁ %-.100s × %s ÎÅ ÍÏÖÅÔ ÉÚÍÅÎÑÔÓÑ"
spa "La tabla destino %-.100s del %s no es actualizable"
- swe "Tabel %-.100s använd med '%s' är inte uppdateringsbar"
+ swe "Tabell %-.100s använd med '%s' är inte uppdateringsbar"
ukr "ôÁÂÌÉÃÑ %-.100s Õ %s ÎÅ ÍÏÖÅ ÏÎÏ×ÌÀ×ÁÔÉÓØ"
ER_FEATURE_DISABLED
eng "The '%s' feature is disabled; you need MySQL built with '%s' to have it working"
@@ -5347,14 +5347,14 @@ ER_SP_NO_RETSET_IN_FUNC 0A000
ER_CANT_CREATE_GEOMETRY_OBJECT 22003
eng "Cannot get geometry object from data you send to the GEOMETRY field"
ER_FAILED_ROUTINE_BREAK_BINLOG
- eng "A routine failed and is declared to modify data and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes"
+ eng "A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes"
ER_BINLOG_UNSAFE_ROUTINE
- eng "This routine is declared to be non-deterministic and to modify data and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)"
+ eng "This routine has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)"
ER_BINLOG_CREATE_ROUTINE_NEED_SUPER
- eng "You do not have SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)"
+ eng "You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)"
ER_EXEC_STMT_WITH_OPEN_CURSOR
eng "You can't execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it."
ER_STMT_HAS_NO_OPEN_CURSOR
- eng "The statement (%d) has no open cursor."
+ eng "The statement (%lu) has no open cursor."
ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
eng "Explicit or implicit commit is not allowed in stored function or trigger."
diff --git a/sql/slave.cc b/sql/slave.cc
index 60812469671..c6c0de7160b 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -5002,7 +5002,7 @@ end:
}
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class I_List_iterator<i_string>;
template class I_List_iterator<i_string_pair>;
#endif
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 29898437cfb..e4dc64c993d 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -310,16 +310,16 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head()
- :Item_arena((bool)FALSE), m_returns_cs(NULL), m_has_return(FALSE),
+ :Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
+ m_returns_cs(NULL), m_has_return(FALSE),
m_simple_case(FALSE), m_multi_results(FALSE), m_in_handler(FALSE)
{
extern byte *
sp_table_key(const byte *ptr, uint *plen, my_bool first);
- extern byte
+ extern byte
*sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first);
DBUG_ENTER("sp_head::sp_head");
- state= INITIALIZED_FOR_SP;
m_backpatch.empty();
m_lex.empty();
hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
@@ -509,7 +509,7 @@ sp_head::destroy()
delete i;
delete_dynamic(&m_instr);
m_pcont->destroy();
- free_items(free_list);
+ free_items();
/*
If we have non-empty LEX stack then we just came out of parser with
@@ -574,7 +574,7 @@ sp_head::execute(THD *thd)
sp_rcontext *ctx;
int ret= 0;
uint ip= 0;
- Item_arena *old_arena;
+ Query_arena *old_arena;
query_id_t old_query_id;
TABLE *old_derived_tables;
LEX *old_lex;
@@ -596,7 +596,6 @@ sp_head::execute(THD *thd)
ctx->clear_handler();
thd->query_error= 0;
old_arena= thd->current_arena;
- thd->current_arena= this;
/*
We have to save/restore this info when we are changing call level to
@@ -636,9 +635,18 @@ sp_head::execute(THD *thd)
break;
DBUG_PRINT("execute", ("Instruction %u", ip));
thd->set_time(); // Make current_time() et al work
+ /*
+ We have to set thd->current_arena before executing the instruction
+ to store in the instruction free_list all new items, created
+ during the first execution (for example expanding of '*' or the
+ items made during other permanent subquery transformations).
+ */
+ thd->current_arena= i;
ret= i->execute(thd, &ip);
if (i->free_list)
cleanup_items(i->free_list);
+ i->state= Query_arena::EXECUTED;
+
// Check if an exception has occurred and a handler has been found
// Note: We havo to check even if ret==0, since warnings (and some
// errors don't return a non-zero value.
@@ -680,8 +688,8 @@ sp_head::execute(THD *thd)
DBUG_ASSERT(!thd->derived_tables);
thd->derived_tables= old_derived_tables;
- cleanup_items(thd->current_arena->free_list);
thd->current_arena= old_arena;
+ state= EXECUTED;
done:
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
@@ -713,8 +721,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
sp_rcontext *nctx = NULL;
uint i;
int ret;
- MEM_ROOT *old_mem_root, call_mem_root;
- Item *old_free_list, *call_free_list;
+ MEM_ROOT call_mem_root;
+ Query_arena call_arena(&call_mem_root, INITIALIZED_FOR_SP), backup_arena;
if (argcount != params)
{
@@ -726,14 +734,11 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
}
init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
- old_mem_root= thd->mem_root;
- thd->mem_root= &call_mem_root;
- old_free_list= thd->free_list; // Keep the old list
- thd->free_list= NULL; // Start a new one
+
// QQ Should have some error checking here? (types, etc...)
nctx= new sp_rcontext(csize, hmax, cmax);
- nctx->callers_mem_root= old_mem_root;
+ nctx->callers_mem_root= thd->mem_root;
for (i= 0 ; i < argcount ; i++)
{
sp_pvar_t *pvar = m_pcont->find_pvar(i);
@@ -759,15 +764,16 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
}
}
thd->spcont= nctx;
+ thd->set_n_backup_item_arena(&call_arena, &backup_arena);
+ /* mem_root was moved to backup_arena */
+ DBUG_ASSERT(nctx->callers_mem_root == backup_arena.mem_root);
ret= execute(thd);
// Partially restore context now.
// We still need the call mem root and free list for processing
// of the result.
- call_free_list= thd->free_list;
- thd->free_list= old_free_list;
- thd->mem_root= old_mem_root;
+ thd->restore_backup_item_arena(&call_arena, &backup_arena);
if (m_type == TYPE_ENUM_FUNCTION && ret == 0)
{
@@ -787,8 +793,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
thd->spcont= octx;
// Now get rid of the rest of the callee context
- cleanup_items(call_free_list);
- free_items(call_free_list);
+ call_arena.free_items();
free_root(&call_mem_root, MYF(0));
DBUG_RETURN(ret);
@@ -820,8 +825,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
sp_rcontext *octx = thd->spcont;
sp_rcontext *nctx = NULL;
my_bool tmp_octx = FALSE; // True if we have allocated a temporary octx
- MEM_ROOT *old_mem_root, call_mem_root;
- Item *old_free_list, *call_free_list;
+ MEM_ROOT call_mem_root;
+ Query_arena call_arena(&call_mem_root, INITIALIZED_FOR_SP), backup_arena;
if (args->elements != params)
{
@@ -831,10 +836,6 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
}
init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
- old_mem_root= thd->mem_root;
- thd->mem_root= &call_mem_root;
- old_free_list= thd->free_list; // Keep the old list
- thd->free_list= NULL; // Start a new one
if (csize > 0 || hmax > 0 || cmax > 0)
{
@@ -899,14 +900,11 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
}
if (! ret)
+ {
+ thd->set_n_backup_item_arena(&call_arena, &backup_arena);
ret= execute(thd);
-
- // Partially restore context now.
- // We still need the call mem root and free list for processing
- // of out parameters.
- call_free_list= thd->free_list;
- thd->free_list= old_free_list;
- thd->mem_root= old_mem_root;
+ thd->restore_backup_item_arena(&call_arena, &backup_arena);
+ }
if (!ret && csize > 0)
{
@@ -981,8 +979,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
thd->spcont= octx;
// Now get rid of the rest of the callee context
- cleanup_items(call_free_list);
- free_items(call_free_list);
+ call_arena.free_items();
thd->lex->unit.cleanup();
free_root(&call_mem_root, MYF(0));
@@ -1276,6 +1273,13 @@ void sp_head::add_instr(sp_instr *instr)
{
instr->free_list= m_thd->free_list;
m_thd->free_list= 0;
+ /*
+ Memory root of every instruction is designated for permanent
+ transformations (optimizations) made on the parsed tree during
+ the first execution. It points to the memory root of the
+ entire stored procedure, as their life span is equal.
+ */
+ instr->mem_root= &main_mem_root;
insert_dynamic(&m_instr, (gptr)&instr);
}
@@ -1470,13 +1474,6 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
they want to store some value in local variable, pass return value and
etc... So their life time should be longer than one instruction.
- Probably we can call destructors for most of them then we are leaving
- routine. But this won't help much as they are allocated in main query
- MEM_ROOT anyway. So they all go to global thd->free_list.
-
- May be we can use some other MEM_ROOT for this purprose ???
-
- What else should we do for cleanup ?
cleanup_items() is called in sp_head::execute()
*/
return res;
@@ -2312,7 +2309,7 @@ sp_head::add_used_tables_to_table_list(THD *thd,
TABLE_LIST ***query_tables_last_ptr)
{
uint i;
- Item_arena *arena, backup;
+ Query_arena *arena, backup;
bool result= FALSE;
DBUG_ENTER("sp_head::add_used_tables_to_table_list");
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 49eabce246b..aaef5a3d50e 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -74,11 +74,12 @@ sp_name *
sp_name_current_db_new(THD *thd, LEX_STRING name);
-class sp_head :private Item_arena
+class sp_head :private Query_arena
{
sp_head(const sp_head &); /* Prevent use of these */
void operator=(sp_head &);
+ MEM_ROOT main_mem_root;
public:
int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
@@ -273,7 +274,7 @@ private:
// "Instructions"...
//
-class sp_instr : public Sql_alloc
+class sp_instr :public Query_arena, public Sql_alloc
{
sp_instr(const sp_instr &); /* Prevent use of these */
void operator=(sp_instr &);
@@ -281,17 +282,16 @@ class sp_instr : public Sql_alloc
public:
uint marked;
- Item *free_list; // My Items
uint m_ip; // My index
sp_pcontext *m_ctx; // My parse context
// Should give each a name or type code for debugging purposes?
sp_instr(uint ip, sp_pcontext *ctx)
- :Sql_alloc(), marked(0), free_list(0), m_ip(ip), m_ctx(ctx)
+ :Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
{}
virtual ~sp_instr()
- { free_items(free_list); }
+ { free_items(); }
// Execute this instrution. '*nextp' will be set to the index of the next
// instruction to execute. (For most instruction this will be the
@@ -377,6 +377,10 @@ public:
return (uint)m_lex->sql_command;
}
+ void disable_query_cache()
+ {
+ m_lex->safe_to_cache_query= 0;
+ }
private:
LEX *m_lex;
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 61cd7a9300f..aacb9254753 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -169,6 +169,17 @@ sp_rcontext::pop_cursors(uint count)
*
*/
+sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper)
+ :m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL)
+{
+ /*
+ currsor can't be stored in QC, so we should prevent opening QC for
+ try to write results which are absent.
+ */
+ lex_keeper->disable_query_cache();
+}
+
+
/*
pre_open cursor
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 864dc3df146..b188805435f 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -203,11 +203,7 @@ class sp_cursor : public Sql_alloc
{
public:
- sp_cursor(sp_lex_keeper *lex_keeper)
- : m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL)
- {
- /* Empty */
- }
+ sp_cursor(sp_lex_keeper *lex_keeper);
virtual ~sp_cursor()
{
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 04da0dd5eb5..c1044d31c46 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -5325,7 +5325,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
Instantiate used templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List_iterator<LEX_COLUMN>;
template class List_iterator<LEX_USER>;
template class List<LEX_COLUMN>;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index a1887996d00..d8bbb686ba2 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1611,8 +1611,18 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
*/
if (discover_retry_count++ != 0)
goto err;
- if (ha_create_table_from_engine(thd, db, name, TRUE) != 0)
+ if (ha_create_table_from_engine(thd, db, name) > 0)
+ {
+ /* Give right error message */
+ thd->clear_error();
+ DBUG_PRINT("error", ("Dicovery of %s/%s failed", db, name));
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "Failed to open '%-.64s', error while "
+ "unpacking from engine",
+ MYF(0), name);
+
goto err;
+ }
mysql_reset_errors(thd, 1); // Clear warnings
thd->clear_error(); // Clear error message
@@ -2626,7 +2636,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
uint length=(uint) strlen(name);
char name_buff[NAME_LEN+1];
-
if (item->cached_table)
{
/*
@@ -2693,10 +2702,13 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
db= name_buff;
}
+ bool search_global= item->item_flags & MY_ITEM_PREFER_1ST_TABLE;
if (table_name && table_name[0])
{ /* Qualified field */
- bool found_table=0;
- for (; tables; tables= tables->next_local)
+ bool found_table=0;
+ uint table_idx= 0;
+ for (; tables; tables= search_global?tables->next_global:tables->next_local,
+ table_idx++)
{
/* TODO; Ensure that db and tables->db always points to something ! */
if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) &&
@@ -2732,6 +2744,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
return (Field*) 0;
}
found=find;
+ if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE)
+ break;
}
}
}
@@ -2756,9 +2770,10 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
return (Field*) not_found_field;
return (Field*) 0;
}
-
bool allow_rowid= tables && !tables->next_local; // Only one table
- for (; tables ; tables= tables->next_local)
+ uint table_idx= 0;
+ for (; tables ; tables= search_global?tables->next_global:tables->next_local,
+ table_idx++)
{
if (!tables->table && !tables->ancestor)
{
@@ -2793,7 +2808,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where);
return (Field*) 0;
}
- found=field;
+ found= field;
+ if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE)
+ break;
}
}
if (found)
@@ -3020,7 +3037,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
Item *item;
List_iterator<Item> it(fields);
- Item_arena *arena, backup;
+ Query_arena *arena, backup;
DBUG_ENTER("setup_wild");
/*
@@ -3051,7 +3068,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
}
else if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it,
- any_privileges, arena != 0))
+ any_privileges))
{
if (arena)
thd->restore_backup_item_arena(arena, &backup);
@@ -3304,8 +3321,6 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
any_privileges 0 If we should ensure that we have SELECT privileges
for all columns
1 If any privilege is ok
- allocate_view_names if true view names will be copied to current Item_arena
- memory (made for SP/PS)
RETURN
0 ok
'it' is updated to point at last inserted
@@ -3315,7 +3330,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
bool
insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
const char *table_name, List_iterator<Item> *it,
- bool any_privileges, bool allocate_view_names)
+ bool any_privileges)
{
/* allocate variables on stack to avoid pool alloaction */
Field_iterator_table table_iter;
@@ -3506,25 +3521,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
field->query_id=thd->query_id;
table->used_keys.intersect(field->part_of_key);
}
- else if (allocate_view_names &&
- thd->lex->current_select->first_execution)
- {
- Item_field *item;
- if (alias_used)
- item= new Item_field(0,
- thd->strdup(tables->alias),
- thd->strdup(field_name));
- else
- item= new Item_field(thd->strdup(tables->view_db.str),
- thd->strdup(tables->view_name.str),
- thd->strdup(field_name));
- /*
- during cleunup() this item will be put in list to replace
- expression from VIEW
- */
- thd->nocheck_register_item_tree_change(it->ref(), item,
- thd->mem_root);
- }
}
/*
All fields are used in case if usual tables (in case of view used
@@ -3561,7 +3557,7 @@ err:
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
{
SELECT_LEX *select_lex= thd->lex->current_select;
- Item_arena *arena= thd->current_arena, backup;
+ Query_arena *arena= thd->current_arena, backup;
bool save_wrapper= thd->lex->current_select->no_wrap_view_item;
TABLE_LIST *table= NULL; // For HP compilers
DBUG_ENTER("setup_conds");
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 165ce61d5d1..20f48da9283 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -49,7 +49,7 @@ char internal_table_name[2]= "*";
** Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
/* Used templates */
template class List<Key>;
template class List_iterator<Key>;
@@ -156,18 +156,21 @@ bool foreign_key_prefix(Key *a, Key *b)
/****************************************************************************
** Thread specific functions
****************************************************************************/
+/*
+ Pass nominal parameters to Statement constructor only to ensure that
+ the destructor works OK in case of error. The main_mem_root will be
+ re-initialized in init().
+*/
THD::THD()
- :user_time(0), global_read_lock(0), is_fatal_error(0),
+ :Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0),
+ user_time(0), global_read_lock(0), is_fatal_error(0),
rand_used(0), time_zone_used(0),
last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0),
in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE),
spcont(NULL)
{
current_arena= this;
-#ifndef DBUG_OFF
- backup_arena= 0;
-#endif
host= user= priv_user= db= ip= 0;
catalog= (char*)"std"; // the only catalog we have for now
host_or_ip= "connecting host";
@@ -420,8 +423,6 @@ THD::~THD()
#ifndef DBUG_OFF
dbug_sentry= THD_SENTRY_GONE;
#endif
- /* Reset stmt_backup.mem_root to not double-free memory from thd.mem_root */
- clear_alloc_root(&stmt_backup.main_mem_root);
DBUG_VOID_RETURN;
}
@@ -524,7 +525,7 @@ void THD::cleanup_after_query()
next_insert_id= 0;
}
/* Free Items that were created during this execution */
- free_items(free_list);
+ free_items();
/*
In the rest of code we assume that free_list never points to garbage:
Keep this predicate true.
@@ -1474,56 +1475,25 @@ void select_dumpvar::cleanup()
}
-/*
- Create arena for already constructed THD.
-
- SYNOPSYS
- Item_arena()
- thd - thread for which arena is created
-
- DESCRIPTION
- Create arena for already existing THD using its variables as parameters
- for memory root initialization.
-*/
-Item_arena::Item_arena(THD* thd)
- :free_list(0), mem_root(&main_mem_root),
- state(INITIALIZED)
-{
- init_sql_alloc(&main_mem_root,
- thd->variables.query_alloc_block_size,
- thd->variables.query_prealloc_size);
-}
-
-
-/*
- Create arena and optionally initialize memory root.
-
- SYNOPSYS
- Item_arena()
- init_mem_root - whenever we need to initialize memory root
-
- DESCRIPTION
- Create arena and optionally initialize memory root with minimal
- possible parameters.
-
- NOTE
- We use this constructor when arena is part of THD, but reinitialize
- its memory root in THD::init_for_queries() before execution of real
- statements.
-*/
-Item_arena::Item_arena(bool init_mem_root)
- :free_list(0), mem_root(&main_mem_root),
- state(CONVENTIONAL_EXECUTION)
+Query_arena::Type Query_arena::type() const
{
- if (init_mem_root)
- init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+ DBUG_ASSERT(0); /* Should never be called */
+ return STATEMENT;
}
-Item_arena::Type Item_arena::type() const
+void Query_arena::free_items()
{
- DBUG_ASSERT(0); /* Should never be called */
- return STATEMENT;
+ Item *next;
+ DBUG_ENTER("Query_arena::free_items");
+ /* This works because items are allocated with sql_alloc() */
+ for (; free_list; free_list= next)
+ {
+ next= free_list->next;
+ free_list->delete_self();
+ }
+ /* Postcondition: free_list is 0 */
+ DBUG_VOID_RETURN;
}
@@ -1531,9 +1501,10 @@ Item_arena::Type Item_arena::type() const
Statement functions
*/
-Statement::Statement(THD *thd)
- :Item_arena(thd),
- id(++thd->statement_id_counter),
+Statement::Statement(enum enum_state state_arg, ulong id_arg,
+ ulong alloc_block_size, ulong prealloc_size)
+ :Query_arena(&main_mem_root, state_arg),
+ id(id_arg),
set_query_id(1),
allow_sum_func(0),
lex(&main_lex),
@@ -1542,28 +1513,11 @@ Statement::Statement(THD *thd)
cursor(0)
{
name.str= NULL;
-}
-
-/*
- This constructor is called when statement is a subobject of THD:
- Some variables are initialized in THD::init due to locking problems
- This statement object will be used to
-*/
-
-Statement::Statement()
- :Item_arena((bool)TRUE),
- id(0),
- set_query_id(1),
- allow_sum_func(0), /* initialized later */
- lex(&main_lex),
- query(0), /* these two are set */
- query_length(0), /* in alloc_query() */
- cursor(0)
-{
+ init_sql_alloc(&main_mem_root, alloc_block_size, prealloc_size);
}
-Item_arena::Type Statement::type() const
+Query_arena::Type Statement::type() const
{
return STATEMENT;
}
@@ -1611,41 +1565,32 @@ void THD::end_statement()
}
-void Item_arena::set_n_backup_item_arena(Item_arena *set, Item_arena *backup)
+void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup)
{
- DBUG_ENTER("Item_arena::set_n_backup_item_arena");
- DBUG_ASSERT(backup_arena == 0);
+ DBUG_ENTER("Query_arena::set_n_backup_item_arena");
+ DBUG_ASSERT(backup->is_backup_arena == FALSE);
backup->set_item_arena(this);
set_item_arena(set);
#ifndef DBUG_OFF
- backup_arena= 1;
+ backup->is_backup_arena= TRUE;
#endif
DBUG_VOID_RETURN;
}
-void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup)
+void Query_arena::restore_backup_item_arena(Query_arena *set, Query_arena *backup)
{
- DBUG_ENTER("Item_arena::restore_backup_item_arena");
+ DBUG_ENTER("Query_arena::restore_backup_item_arena");
+ DBUG_ASSERT(backup->is_backup_arena);
set->set_item_arena(this);
set_item_arena(backup);
#ifndef DBUG_OFF
- backup_arena= 0;
-#endif
-#ifdef NOT_NEEDED_NOW
- /*
- Reset backup mem_root to avoid its freeing.
- Since Item_arena's mem_root is freed only when it is part of Statement
- we need this only if we use some Statement's arena as backup storage.
- But we do this only with THD::stmt_backup and this Statement is specially
- handled in this respect. So this code is not really needed now.
- */
- clear_alloc_root(&backup->mem_root);
+ backup->is_backup_arena= FALSE;
#endif
DBUG_VOID_RETURN;
}
-void Item_arena::set_item_arena(Item_arena *set)
+void Query_arena::set_item_arena(Query_arena *set)
{
mem_root= set->mem_root;
free_list= set->free_list;
@@ -1654,6 +1599,11 @@ void Item_arena::set_item_arena(Item_arena *set)
Statement::~Statement()
{
+ /*
+ We must free `main_mem_root', not `mem_root' (pointer), to work
+ correctly if this statement is used as a backup statement,
+ for which `mem_root' may point to some other statement.
+ */
free_root(&main_mem_root, MYF(0));
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index d2095503fe5..1f232b9ca21 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -631,6 +631,13 @@ typedef struct system_status_var
ulong filesort_range_count;
ulong filesort_rows;
ulong filesort_scan_count;
+ /* Ppepared statements and binary protocol */
+ ulong com_stmt_prepare;
+ ulong com_stmt_execute;
+ ulong com_stmt_send_long_data;
+ ulong com_stmt_fetch;
+ ulong com_stmt_reset;
+ ulong com_stmt_close;
double last_query_cost;
} STATUS_VAR;
@@ -640,13 +647,13 @@ typedef struct system_status_var
variable in system_status_var
*/
-#define last_system_status_var filesort_scan_count
+#define last_system_status_var com_stmt_close
void free_tmp_table(THD *thd, TABLE *entry);
-class Item_arena
+class Query_arena
{
public:
/*
@@ -654,17 +661,19 @@ public:
itself to the list on creation (see Item::Item() for details))
*/
Item *free_list;
- MEM_ROOT main_mem_root;
MEM_ROOT *mem_root; // Pointer to current memroot
#ifndef DBUG_OFF
- bool backup_arena;
+ bool is_backup_arena; /* True if this arena is used for backup. */
+#define INIT_ARENA_DBUG_INFO is_backup_arena= 0
+#else
+#define INIT_ARENA_DBUG_INFO
#endif
- enum enum_state
+ enum enum_state
{
INITIALIZED= 0, INITIALIZED_FOR_SP= 1, PREPARED= 2,
CONVENTIONAL_EXECUTION= 3, EXECUTED= 4, ERROR= -1
};
-
+
enum_state state;
/* We build without RTTI, so dynamic_cast can't be used. */
@@ -673,25 +682,22 @@ public:
STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE
};
+ Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) :
+ free_list(0), mem_root(mem_root_arg), state(state_arg)
+ { INIT_ARENA_DBUG_INFO; }
/*
- This constructor is used only when Item_arena is created as
- backup storage for another instance of Item_arena.
- */
- Item_arena() {};
- /*
- Create arena for already constructed THD using its variables as
- parameters for memory root initialization.
+ This constructor is used only when Query_arena is created as
+ backup storage for another instance of Query_arena.
*/
- Item_arena(THD *thd);
- /*
- Create arena and optionally init memory root with minimal values.
- Particularly used if Item_arena is part of Statement.
- */
- Item_arena(bool init_mem_root);
+ Query_arena() { INIT_ARENA_DBUG_INFO; }
+
+#undef INIT_ARENA_DBUG_INFO
virtual Type type() const;
- virtual ~Item_arena() {};
+ virtual ~Query_arena() {};
inline bool is_stmt_prepare() const { return state == INITIALIZED; }
+ inline bool is_first_sp_execute() const
+ { return state == INITIALIZED_FOR_SP; }
inline bool is_stmt_prepare_or_first_sp_execute() const
{ return (int)state < (int)PREPARED; }
inline bool is_first_stmt_execute() const { return state == PREPARED; }
@@ -699,6 +705,7 @@ public:
{ return state == PREPARED || state == EXECUTED; }
inline bool is_conventional() const
{ return state == CONVENTIONAL_EXECUTION; }
+
inline gptr alloc(unsigned int size) { return alloc_root(mem_root,size); }
inline gptr calloc(unsigned int size)
{
@@ -721,9 +728,11 @@ public:
return ptr;
}
- void set_n_backup_item_arena(Item_arena *set, Item_arena *backup);
- void restore_backup_item_arena(Item_arena *set, Item_arena *backup);
- void set_item_arena(Item_arena *set);
+ void set_n_backup_item_arena(Query_arena *set, Query_arena *backup);
+ void restore_backup_item_arena(Query_arena *set, Query_arena *backup);
+ void set_item_arena(Query_arena *set);
+
+ void free_items();
};
@@ -743,12 +752,13 @@ class Cursor;
be used explicitly.
*/
-class Statement: public Item_arena
+class Statement: public Query_arena
{
Statement(const Statement &rhs); /* not implemented: */
Statement &operator=(const Statement &rhs); /* non-copyable */
public:
- /* FIXME: must be private */
+ /* FIXME: these must be protected */
+ MEM_ROOT main_mem_root;
LEX main_lex;
/*
@@ -806,13 +816,11 @@ public:
public:
- /*
- This constructor is called when statement is a subobject of THD:
- some variables are initialized in THD::init due to locking problems
- */
- Statement();
+ /* This constructor is called for backup statements */
+ Statement() { clear_alloc_root(&main_mem_root); }
- Statement(THD *thd);
+ Statement(enum enum_state state_arg, ulong id_arg,
+ ulong alloc_block_size, ulong prealloc_size);
virtual ~Statement();
/* Assign execution context (note: not all members) of given stmt to self */
@@ -955,11 +963,6 @@ public:
/* all prepared statements and cursors of this connection */
Statement_map stmt_map;
/*
- keeps THD state while it is used for active statement
- Note: we perform special cleanup for it in THD destructor.
- */
- Statement stmt_backup;
- /*
A pointer to the stack frame of handle_one_connection(),
which is called first in the thread for handling a client
*/
@@ -1039,7 +1042,7 @@ public:
#endif
struct st_my_thread_var *mysys_var;
/*
- Type of current query: COM_PREPARE, COM_QUERY, etc. Set from
+ Type of current query: COM_STMT_PREPARE, COM_QUERY, etc. Set from
first byte of the packet in do_command()
*/
enum enum_server_command command;
@@ -1107,9 +1110,9 @@ public:
Item_change_list change_list;
/*
- Current prepared Item_arena if there one, or 0
+ Current prepared Query_arena if there one, or 0
*/
- Item_arena *current_arena;
+ Query_arena *current_arena;
/*
next_insert_id is set on SET INSERT_ID= #. This is used as the next
generated auto_increment value in handler.cc
@@ -1186,7 +1189,7 @@ public:
bool query_error, bootstrap, cleanup_done;
bool tmp_table_used;
bool charset_is_system_charset, charset_is_collation_connection;
- bool slow_command;
+ bool enable_slow_log; /* enable slow log for current statement */
bool no_trans_update, abort_on_warning;
bool got_warning; /* Set on call to push_warning() */
bool no_warnings_for_error; /* no warnings on call to my_error() */
@@ -1331,13 +1334,9 @@ public:
return 0;
#endif
}
- inline bool only_prepare()
- {
- return command == COM_PREPARE;
- }
inline bool fill_derived_tables()
{
- return !only_prepare() && !lex->only_view_structure();
+ return !current_arena->is_stmt_prepare() && !lex->only_view_structure();
}
inline gptr trans_alloc(unsigned int size)
{
@@ -1370,20 +1369,20 @@ public:
inline void fatal_error()
{
is_fatal_error= 1;
- net.report_error= 1;
+ net.report_error= 1;
DBUG_PRINT("error",("Fatal error set"));
}
inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset();
- inline Item_arena *change_arena_if_needed(Item_arena *backup)
+ inline Query_arena *change_arena_if_needed(Query_arena *backup)
{
/*
use new arena if we are in a prepared statements and we have not
already changed to use this arena.
*/
if (!current_arena->is_conventional() &&
- mem_root != &current_arena->main_mem_root)
+ mem_root != current_arena->mem_root)
{
set_n_backup_item_arena(current_arena, backup);
return current_arena;
@@ -1428,10 +1427,10 @@ public:
};
#define tmp_disable_binlog(A) \
- ulong save_options= (A)->options; \
- (A)->options&= ~OPTION_BIN_LOG;
+ {ulong tmp_disable_binlog__save_options= (A)->options; \
+ (A)->options&= ~OPTION_BIN_LOG
-#define reenable_binlog(A) (A)->options= save_options;
+#define reenable_binlog(A) (A)->options= tmp_disable_binlog__save_options;}
/* Flags for the THD::system_thread (bitmap) variable */
#define SYSTEM_THREAD_DELAYED_INSERT 1
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index d782744162d..25fef8b0ad6 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -790,7 +790,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
if (!dont_send_ok)
{
db_type table_type;
- if ((table_type=get_table_type(path)) == DB_TYPE_UNKNOWN)
+ if ((table_type=get_table_type(thd, path)) == DB_TYPE_UNKNOWN)
{
my_error(ER_NO_SUCH_TABLE, MYF(0),
table_list->db, table_list->table_name);
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 9356ee04c45..e905f93b860 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -422,7 +422,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
}
}
- if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0, 0))
+ if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0))
goto err0;
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5ca75554c6f..2ce81d8815e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1988,10 +1988,22 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par,
int
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
+ int res;
+ LEX *lex= thd->lex;
+ SELECT_LEX *lex_current_select_save= lex->current_select;
DBUG_ENTER("select_insert::prepare");
unit= u;
- if (check_insert_fields(thd, table_list, *fields, values, !insert_into_view))
+ /*
+ Since table in which we are going to insert is added to the first
+ select, LEX::current_select should point to the first select while
+ we are fixing fields from insert list.
+ */
+ lex->current_select= &lex->select_lex;
+ res= check_insert_fields(thd, table_list, *fields, values,
+ !insert_into_view);
+ lex->current_select= lex_current_select_save;
+ if (res)
DBUG_RETURN(1);
/*
if it is INSERT into join view then check_insert_fields already found
@@ -2003,12 +2015,12 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
Is table which we are changing used somewhere in other parts of
query
*/
- if (!(thd->lex->current_select->options & OPTION_BUFFER_RESULT) &&
+ if (!(lex->current_select->options & OPTION_BUFFER_RESULT) &&
unique_table(table_list, table_list->next_global))
{
/* Using same table for INSERT and SELECT */
- thd->lex->current_select->options|= OPTION_BUFFER_RESULT;
- thd->lex->current_select->join->select_options|= OPTION_BUFFER_RESULT;
+ lex->current_select->options|= OPTION_BUFFER_RESULT;
+ lex->current_select->join->select_options|= OPTION_BUFFER_RESULT;
}
else
{
@@ -2107,9 +2119,12 @@ bool select_insert::send_data(List<Item> &values)
}
if (!(error= write_record(thd, table, &info)))
{
- if (table->triggers)
+ if (table->triggers || info.handle_duplicates == DUP_UPDATE)
{
/*
+ Restore fields of the record since it is possible that they were
+ changed by ON DUPLICATE KEY UPDATE clause.
+
If triggers exist then whey can modify some fields which were not
originally touched by INSERT ... SELECT, so we have to restore
their original values for the next row.
@@ -2362,11 +2377,11 @@ void select_create::abort()
Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List_iterator_fast<List_item>;
#ifndef EMBEDDED_LIBRARY
template class I_List<delayed_insert>;
template class I_List_iterator<delayed_insert>;
template class I_List<delayed_row>;
#endif /* EMBEDDED_LIBRARY */
-#endif /* __GNUC__ */
+#endif /* HAVE_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 1270aab18ae..08f0c3badf7 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -967,7 +967,7 @@ int yylex(void *arg, void *yythd)
{
THD* thd= (THD*)yythd;
if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) &&
- (thd->command != COM_PREPARE))
+ (thd->command != COM_STMT_PREPARE))
{
lex->safe_to_cache_query= 0;
lex->found_semicolon=(char*) lex->ptr;
@@ -1484,8 +1484,8 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
We have to create array in prepared statement memory if it is
prepared statement
*/
- Item_arena *arena= thd->current_arena;
- return (ref_pointer_array=
+ Query_arena *arena= thd->current_arena;
+ return (ref_pointer_array=
(Item **)arena->alloc(sizeof(Item*) *
(item_list.elements +
select_n_having_items +
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 8af416f0ce8..5cf0b66598f 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -114,6 +114,14 @@ enum enum_sp_data_access
SP_MODIFIES_SQL_DATA
};
+const LEX_STRING sp_data_access_name[]=
+{
+ { (char*) STRING_WITH_LEN("") },
+ { (char*) STRING_WITH_LEN("CONTAINS SQL") },
+ { (char*) STRING_WITH_LEN("NO SQL") },
+ { (char*) STRING_WITH_LEN("READS SQL DATA") },
+ { (char*) STRING_WITH_LEN("MODIFIES SQL DATA") }
+};
#define DERIVED_SUBQUERY 1
#define DERIVED_VIEW 2
@@ -522,7 +530,19 @@ public:
query processing end even if we use temporary table
*/
bool subquery_in_having;
- bool first_execution; /* first execution in SP or PS */
+ /*
+ This variable is required to ensure proper work of subqueries and
+ stored procedures. Generally, one should use the states of
+ Query_arena to determine if it's a statement prepare or first
+ execution of a stored procedure. However, in case when there was an
+ error during the first execution of a stored procedure, the SP body
+ is not expelled from the SP cache. Therefore, a deeply nested
+ subquery might be left unoptimized. So we need this per-subquery
+ variable to inidicate the optimization/execution state of every
+ subquery. Prepared statements work OK in that regard, as in
+ case of an error during prepare the PS is not created.
+ */
+ bool first_execution;
bool first_cond_optimization;
/* do not wrap view fields with Item_ref */
bool no_wrap_view_item;
@@ -622,6 +642,11 @@ public:
static void print_order(String *str, ORDER *order);
void print_limit(THD *thd, String *str);
void fix_prepare_information(THD *thd, Item **conds);
+ /*
+ Destroy the used execution plan (JOIN) of this subtree (this
+ SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs).
+ */
+ bool cleanup();
};
typedef class st_select_lex SELECT_LEX;
diff --git a/sql/sql_map.cc b/sql/sql_map.cc
index 9346f3df305..56b4b765355 100644
--- a/sql/sql_map.cc
+++ b/sql/sql_map.cc
@@ -138,7 +138,7 @@ void unmap_file(mapped_files *map)
** Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
/* Used templates */
template class I_List<mapped_files>;
template class I_List_iterator<mapped_files>;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index be7ba7d571d..d6a719e65f9 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -71,7 +71,6 @@ static void remove_escape(char *name);
static void refresh_status(void);
static bool append_file_to_dir(THD *thd, const char **filename_ptr,
const char *table_name);
-static void log_slow_query(THD *thd);
const char *any_db="*any*"; // Special symbol for check_access
@@ -1508,10 +1507,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->command=command;
/*
- Commands which will always take a long time should be marked with
- this so that they will not get logged to the slow query log
+ Commands which always take a long time are logged into
+ the slow log only if opt_log_slow_admin_statements is set.
*/
- thd->slow_command=FALSE;
+ thd->enable_slow_log= TRUE;
thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
thd->set_time();
VOID(pthread_mutex_lock(&LOCK_thread_count));
@@ -1551,7 +1550,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
uint tbl_len= *(uchar*) (packet + db_len + 1);
statistic_increment(thd->status_var.com_other, &LOCK_status);
- thd->slow_command= TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
db= thd->alloc(db_len + tbl_len + 2);
tbl_name= strmake(db, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len);
@@ -1635,32 +1634,32 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
break;
}
- case COM_EXECUTE:
+ case COM_STMT_EXECUTE:
{
mysql_stmt_execute(thd, packet, packet_length);
break;
}
- case COM_FETCH:
+ case COM_STMT_FETCH:
{
mysql_stmt_fetch(thd, packet, packet_length);
break;
}
- case COM_LONG_DATA:
+ case COM_STMT_SEND_LONG_DATA:
{
mysql_stmt_get_longdata(thd, packet, packet_length);
break;
}
- case COM_PREPARE:
+ case COM_STMT_PREPARE:
{
mysql_stmt_prepare(thd, packet, packet_length, 0);
break;
}
- case COM_CLOSE_STMT:
+ case COM_STMT_CLOSE:
{
- mysql_stmt_free(thd, packet);
+ mysql_stmt_close(thd, packet);
break;
}
- case COM_RESET_STMT:
+ case COM_STMT_RESET:
{
mysql_stmt_reset(thd, packet);
break;
@@ -1689,7 +1688,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif
ulong length= (ulong)(packet_end-packet);
- log_slow_query(thd);
+ log_slow_statement(thd);
/* Remove garbage at start of query */
while (my_isspace(thd->charset(), *packet) && length > 0)
@@ -1858,7 +1857,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
uint32 slave_server_id;
statistic_increment(thd->status_var.com_other,&LOCK_status);
- thd->slow_command = TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
if (check_global_access(thd, REPL_SLAVE_ACL))
break;
@@ -2043,7 +2042,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (thd->net.report_error)
net_send_error(thd);
- log_slow_query(thd);
+ log_slow_statement(thd);
thd->proc_info="cleaning up";
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
@@ -2059,13 +2058,16 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
-static void log_slow_query(THD *thd)
+void log_slow_statement(THD *thd)
{
time_t start_of_query=thd->start_time;
thd->end_time(); // Set start time
- /* If not reading from backup and if the query took too long */
- if (!thd->slow_command && !thd->user_time) // do not log 'slow_command' queries
+ /*
+ Do not log administrative statements unless the appropriate option is
+ set; do not log into slow log if reading from backup.
+ */
+ if (thd->enable_slow_log && !thd->user_time)
{
thd->proc_info="logging slow query";
@@ -2197,7 +2199,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
/*
Read query from packet and store in thd->query
- Used in COM_QUERY and COM_PREPARE
+ Used in COM_QUERY and COM_STMT_PREPARE
DESCRIPTION
Sets the following THD variables:
@@ -2499,7 +2501,7 @@ mysql_execute_command(THD *thd)
lex->prepared_stmt_name.str,
query_len, query_str));
}
- thd->command= COM_PREPARE;
+ thd->command= COM_STMT_PREPARE;
if (!(res= mysql_stmt_prepare(thd, query_str, query_len + 1,
&lex->prepared_stmt_name)))
send_ok(thd, 0L, 0L, "Statement prepared");
@@ -2520,6 +2522,8 @@ mysql_execute_command(THD *thd)
DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n",
lex->prepared_stmt_name.length,
lex->prepared_stmt_name.str));
+ /* We account deallocate in the same manner as mysql_stmt_close */
+ statistic_increment(thd->status_var.com_stmt_close, &LOCK_status);
if ((stmt= thd->stmt_map.find_by_name(&lex->prepared_stmt_name)))
{
thd->stmt_map.erase(stmt);
@@ -2637,7 +2641,7 @@ mysql_execute_command(THD *thd)
check_table_access(thd, SELECT_ACL, all_tables, 0) ||
check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
- thd->slow_command=TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_backup_table(thd, first_table);
break;
@@ -2649,7 +2653,7 @@ mysql_execute_command(THD *thd)
check_table_access(thd, INSERT_ACL, all_tables, 0) ||
check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
- thd->slow_command=TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_restore_table(thd, first_table);
break;
}
@@ -2764,6 +2768,20 @@ mysql_execute_command(THD *thd)
case SQLCOM_CREATE_TABLE:
{
+ /* If CREATE TABLE of non-temporary table, do implicit commit */
+ if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
+ {
+ if (end_active_trans(thd))
+ {
+ res= -1;
+ break;
+ }
+ }
+ else
+ {
+ /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
+ thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
+ }
DBUG_ASSERT(first_table == all_tables && first_table != 0);
bool link_to_local;
// Skip first table, which is the table we are creating
@@ -2906,7 +2924,7 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
- thd->slow_command=TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
if (end_active_trans(thd))
goto error;
else
@@ -2995,7 +3013,7 @@ end_with_restore_list:
goto error;
else
{
- thd->slow_command=TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_alter_table(thd, select_lex->db, lex->name,
&lex->create_info,
first_table, lex->create_list,
@@ -3094,7 +3112,7 @@ end_with_restore_list:
if (check_db_used(thd, all_tables) ||
check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
- thd->slow_command=TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_repair_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
@@ -3114,7 +3132,7 @@ end_with_restore_list:
if (check_db_used(thd, all_tables) ||
check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0))
goto error; /* purecov: inspected */
- thd->slow_command=TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_check_table(thd, first_table, &lex->check_opt);
break;
}
@@ -3124,7 +3142,7 @@ end_with_restore_list:
if (check_db_used(thd, all_tables) ||
check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
- thd->slow_command=TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_analyze_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
@@ -3145,7 +3163,7 @@ end_with_restore_list:
if (check_db_used(thd, all_tables) ||
check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
- thd->slow_command=TRUE;
+ thd->enable_slow_log= opt_log_slow_admin_statements;
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
mysql_recreate_table(thd, first_table, 1) :
mysql_optimize_table(thd, first_table, &lex->check_opt);
@@ -3254,10 +3272,14 @@ end_with_restore_list:
if (first_table->view && !first_table->contain_auto_increment)
thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
-
break;
}
case SQLCOM_TRUNCATE:
+ if (end_active_trans(thd))
+ {
+ res= -1;
+ break;
+ }
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_one_table_access(thd, DELETE_ACL, all_tables))
goto error;
@@ -3351,6 +3373,9 @@ end_with_restore_list:
*/
if (thd->slave_thread)
lex->drop_if_exists= 1;
+
+ /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
+ thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
}
res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
lex->drop_temporary);
@@ -3489,6 +3514,11 @@ end_with_restore_list:
break;
case SQLCOM_CREATE_DB:
{
+ if (end_active_trans(thd))
+ {
+ res= -1;
+ break;
+ }
char *alias;
if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name))
{
@@ -3519,6 +3549,11 @@ end_with_restore_list:
}
case SQLCOM_DROP_DB:
{
+ if (end_active_trans(thd))
+ {
+ res= -1;
+ break;
+ }
if (check_db_name(lex->name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
@@ -5458,6 +5493,21 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
DBUG_RETURN(1);
}
+ if (type == FIELD_TYPE_TIMESTAMP && length)
+ {
+ /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1.
+ In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4),
+ and so on, the display width is ignored.
+ */
+ char buf[32];
+ my_snprintf(buf, sizeof(buf),
+ "TIMESTAMP(%s)", length, system_charset_info);
+ push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER(ER_WARN_DEPRECATED_SYNTAX),
+ buf, "TIMESTAMP");
+ }
+
if (!(new_field= new_create_field(thd, field_name, type, length, decimals,
type_modifier, default_value, on_update_value,
comment, change, interval_list, cs, uint_geom_type)))
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 37efd1d62b9..c97cb037f15 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -19,9 +19,9 @@ This file contains the implementation of prepare and executes.
Prepare:
- - Server gets the query from client with command 'COM_PREPARE';
+ - Server gets the query from client with command 'COM_STMT_PREPARE';
in the following format:
- [COM_PREPARE:1] [query]
+ [COM_STMT_PREPARE:1] [query]
- Parse the query and recognize any parameter markers '?' and
store its information list in lex->param_list
- Allocate a new statement for this prepare; and keep this in
@@ -37,10 +37,10 @@ Prepare:
Prepare-execute:
- - Server gets the command 'COM_EXECUTE' to execute the
+ - Server gets the command 'COM_STMT_EXECUTE' to execute the
previously prepared query. If there is any param markers; then client
will send the data in the following format:
- [COM_EXECUTE:1]
+ [COM_STMT_EXECUTE:1]
[STMT_ID:4]
[NULL_BITS:(param_count+7)/8)]
[TYPES_SUPPLIED_BY_CLIENT(0/1):1]
@@ -55,9 +55,10 @@ Prepare-execute:
Long data handling:
- - Server gets the long data in pieces with command type 'COM_LONG_DATA'.
+ - Server gets the long data in pieces with command type
+ 'COM_STMT_SEND_LONG_DATA'.
- The packet recieved will have the format as:
- [COM_LONG_DATA:1][STMT_ID:4][parameter_number:2][data]
+ [COM_STMT_SEND_LONG_DATA:1][STMT_ID:4][parameter_number:2][data]
- data from the packet is appended to long data value buffer for this
placeholder.
- It's up to the client to check for read data ended. The server doesn't
@@ -104,7 +105,7 @@ public:
Prepared_statement(THD *thd_arg);
virtual ~Prepared_statement();
void setup_set_params();
- virtual Item_arena::Type type() const;
+ virtual Query_arena::Type type() const;
};
static void execute_stmt(THD *thd, Prepared_statement *stmt,
@@ -132,7 +133,7 @@ find_prepared_statement(THD *thd, ulong id, const char *where)
{
Statement *stmt= thd->stmt_map.find(id);
- if (stmt == 0 || stmt->type() != Item_arena::PREPARED_STATEMENT)
+ if (stmt == 0 || stmt->type() != Query_arena::PREPARED_STATEMENT)
{
char llbuf[22];
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf), llstr(id, llbuf),
@@ -839,7 +840,8 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
DBUG_ENTER("insert_params_from_vars");
List_iterator<LEX_STRING> var_it(varnames);
- String str;
+ String buf;
+ const String *val;
uint32 length= 0;
if (query->copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
@@ -850,32 +852,36 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
varname= var_it++;
if (get_var_with_binlog(stmt->thd, *varname, &entry))
DBUG_RETURN(1);
- DBUG_ASSERT(entry != 0);
if (param->set_from_user_var(stmt->thd, entry))
DBUG_RETURN(1);
/* Insert @'escaped-varname' instead of parameter in the query */
- char *buf, *ptr;
- str.length(0);
- if (str.reserve(entry->name.length*2+3))
- DBUG_RETURN(1);
+ if (entry)
+ {
+ char *begin, *ptr;
+ buf.length(0);
+ if (buf.reserve(entry->name.length*2+3))
+ DBUG_RETURN(1);
- buf= str.c_ptr_quick();
- ptr= buf;
- *ptr++= '@';
- *ptr++= '\'';
- ptr+=
- escape_string_for_mysql(&my_charset_utf8_general_ci,
- ptr, 0, entry->name.str, entry->name.length);
- *ptr++= '\'';
- str.length(ptr - buf);
+ begin= ptr= buf.c_ptr_quick();
+ *ptr++= '@';
+ *ptr++= '\'';
+ ptr+= escape_string_for_mysql(&my_charset_utf8_general_ci,
+ ptr, 0, entry->name.str,
+ entry->name.length);
+ *ptr++= '\'';
+ buf.length(ptr - begin);
+ val= &buf;
+ }
+ else
+ val= &my_null_string;
if (param->convert_str_value(stmt->thd))
DBUG_RETURN(1); /* out of memory */
- if (query->replace(param->pos_in_query+length, 1, str))
+ if (query->replace(param->pos_in_query+length, 1, *val))
DBUG_RETURN(1);
- length+= str.length()-1;
+ length+= val->length()-1;
}
DBUG_RETURN(0);
}
@@ -1700,12 +1706,20 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
LEX_STRING *name)
{
LEX *lex;
+ Statement stmt_backup;
Prepared_statement *stmt= new Prepared_statement(thd);
bool error;
DBUG_ENTER("mysql_stmt_prepare");
DBUG_PRINT("prep_query", ("%s", packet));
+ /*
+ If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql.
+ However, it seems handy if com_stmt_prepare is increased always,
+ no matter what kind of prepare is processed.
+ */
+ statistic_increment(thd->status_var.com_stmt_prepare, &LOCK_status);
+
if (stmt == 0)
DBUG_RETURN(TRUE);
@@ -1726,19 +1740,19 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
DBUG_RETURN(TRUE);
}
- thd->set_n_backup_statement(stmt, &thd->stmt_backup);
- thd->set_n_backup_item_arena(stmt, &thd->stmt_backup);
+ thd->set_n_backup_statement(stmt, &stmt_backup);
+ thd->set_n_backup_item_arena(stmt, &stmt_backup);
if (alloc_query(thd, packet, packet_length))
{
- thd->restore_backup_statement(stmt, &thd->stmt_backup);
- thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
+ thd->restore_backup_statement(stmt, &stmt_backup);
+ thd->restore_backup_item_arena(stmt, &stmt_backup);
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
DBUG_RETURN(TRUE);
}
- mysql_log.write(thd, COM_PREPARE, "[%lu] %s", stmt->id, packet);
+ mysql_log.write(thd, thd->command, "[%lu] %s", stmt->id, packet);
thd->current_arena= stmt;
mysql_init_query(thd, (uchar *) thd->query, thd->query_length);
@@ -1757,7 +1771,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
transformation can be reused on execute, we set again thd->mem_root from
stmt->mem_root (see setup_wild for one place where we do that).
*/
- thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
+ thd->restore_backup_item_arena(stmt, &stmt_backup);
if (!error)
error= check_prepared_statement(stmt, test(name));
@@ -1773,7 +1787,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
lex_end(lex);
close_thread_tables(thd);
cleanup_stmt_and_thd_after_use(stmt, thd);
- thd->restore_backup_statement(stmt, &thd->stmt_backup);
+ thd->restore_backup_statement(stmt, &stmt_backup);
thd->current_arena= thd;
if (error)
@@ -1786,7 +1800,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
{
stmt->setup_set_params();
init_stmt_after_parse(thd, stmt->lex);
- stmt->state= Item_arena::PREPARED;
+ stmt->state= Query_arena::PREPARED;
}
DBUG_RETURN(!stmt);
}
@@ -1936,6 +1950,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{
ulong stmt_id= uint4korr(packet);
ulong flags= (ulong) ((uchar) packet[4]);
+ Statement stmt_backup;
Cursor *cursor;
/*
Query text for binary log, or empty string if the query is not put into
@@ -1950,13 +1965,14 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
packet+= 9; /* stmt_id + 5 bytes of flags */
+ statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute")))
DBUG_VOID_RETURN;
DBUG_PRINT("exec_query:", ("%s", stmt->query));
/* Check if we got an error when sending long data */
- if (stmt->state == Item_arena::ERROR)
+ if (stmt->state == Query_arena::ERROR)
{
my_message(stmt->last_errno, stmt->last_error, MYF(0));
DBUG_VOID_RETURN;
@@ -1988,7 +2004,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{
DBUG_PRINT("info",("Using READ_ONLY cursor"));
if (!cursor &&
- !(cursor= stmt->cursor= new (&stmt->main_mem_root) Cursor()))
+ !(cursor= stmt->cursor= new (stmt->mem_root) Cursor(thd)))
DBUG_VOID_RETURN;
/* If lex->result is set, mysql_execute_command will use it */
stmt->lex->result= &cursor->result;
@@ -2012,8 +2028,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query))
goto set_params_data_err;
#endif
- thd->stmt_backup.set_statement(thd);
- thd->set_statement(stmt);
+ thd->set_n_backup_statement(stmt, &stmt_backup);
thd->current_arena= stmt;
reinit_stmt_before_use(thd, stmt->lex);
/* From now cursors assume that thd->mem_root is clean */
@@ -2024,10 +2039,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
my_error(ER_OUTOFMEMORY, 0, expanded_query.length());
goto err;
}
-
- mysql_log.write(thd, COM_EXECUTE, "[%lu] %s", stmt->id,
- expanded_query.length() ? expanded_query.c_ptr() :
- stmt->query);
+ mysql_log.write(thd, thd->command, "[%lu] %s", stmt->id, thd->query);
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -2053,7 +2065,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
reset_stmt_params(stmt);
}
- thd->set_statement(&thd->stmt_backup);
+ thd->set_statement(&stmt_backup);
thd->current_arena= thd;
DBUG_VOID_RETURN;
@@ -2078,9 +2090,12 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
binary log.
*/
String expanded_query;
+ Statement stmt_backup;
DBUG_ENTER("mysql_sql_stmt_execute");
DBUG_ASSERT(thd->free_list == NULL);
+ /* See comment for statistic_increment in mysql_stmt_prepare */
+ statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status);
if (!(stmt= (Prepared_statement*)thd->stmt_map.find_by_name(stmt_name)))
{
@@ -2097,15 +2112,16 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
/* Must go before setting variables, as it clears thd->user_var_events */
mysql_reset_thd_for_next_command(thd);
- thd->set_n_backup_statement(stmt, &thd->stmt_backup);
- thd->set_statement(stmt);
+ thd->set_n_backup_statement(stmt, &stmt_backup);
if (stmt->set_params_from_vars(stmt,
- thd->stmt_backup.lex->prepared_stmt_params,
+ stmt_backup.lex->prepared_stmt_params,
&expanded_query))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
}
+ thd->command= COM_STMT_EXECUTE; /* For nice messages in general log */
execute_stmt(thd, stmt, &expanded_query);
+ thd->set_statement(&stmt_backup);
DBUG_VOID_RETURN;
}
@@ -2137,6 +2153,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
my_error(ER_OUTOFMEMORY, MYF(0), expanded_query->length());
DBUG_VOID_RETURN;
}
+ mysql_log.write(thd, thd->command, "[%lu] %s", stmt->id, thd->query);
/*
At first execution of prepared statement we will perform logical
transformations of the query tree (i.e. negations elimination).
@@ -2149,21 +2166,28 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
mysql_execute_command(thd);
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
+ /*
+ 'start_time' is set in dispatch_command, but THD::query will
+ be freed when we return from this function. So let's log the slow
+ query here.
+ */
+ log_slow_statement(thd);
+ /* Prevent from second logging in the end of dispatch_command */
+ thd->enable_slow_log= FALSE;
close_thread_tables(thd); // to close derived tables
cleanup_stmt_and_thd_after_use(stmt, thd);
reset_stmt_params(stmt);
- thd->set_statement(&thd->stmt_backup);
thd->current_arena= thd;
- if (stmt->state == Item_arena::PREPARED)
- stmt->state= Item_arena::EXECUTED;
+ if (stmt->state == Query_arena::PREPARED)
+ stmt->state= Query_arena::EXECUTED;
DBUG_VOID_RETURN;
}
/*
- COM_FETCH handler: fetches requested amount of rows from cursor
+ COM_STMT_FETCH handler: fetches requested amount of rows from cursor
SYNOPSIS
mysql_stmt_fetch()
@@ -2178,19 +2202,21 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
ulong stmt_id= uint4korr(packet);
ulong num_rows= uint4korr(packet+4);
Prepared_statement *stmt;
+ Statement stmt_backup;
DBUG_ENTER("mysql_stmt_fetch");
+ statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch")))
DBUG_VOID_RETURN;
if (!stmt->cursor || !stmt->cursor->is_open())
{
- my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0));
+ my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0), stmt_id);
DBUG_VOID_RETURN;
}
thd->current_arena= stmt;
- thd->set_n_backup_statement(stmt, &thd->stmt_backup);
+ thd->set_n_backup_statement(stmt, &stmt_backup);
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), QUERY_PRIOR);
@@ -2202,7 +2228,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
- thd->restore_backup_statement(stmt, &thd->stmt_backup);
+ thd->restore_backup_statement(stmt, &stmt_backup);
thd->current_arena= thd;
if (!stmt->cursor->is_open())
@@ -2240,13 +2266,14 @@ void mysql_stmt_reset(THD *thd, char *packet)
Prepared_statement *stmt;
DBUG_ENTER("mysql_stmt_reset");
+ statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset")))
DBUG_VOID_RETURN;
if (stmt->cursor && stmt->cursor->is_open())
stmt->cursor->close();
- stmt->state= Item_arena::PREPARED;
+ stmt->state= Query_arena::PREPARED;
/*
Clear parameters from data which could be set by
@@ -2266,14 +2293,15 @@ void mysql_stmt_reset(THD *thd, char *packet)
Note: we don't send any reply to that command.
*/
-void mysql_stmt_free(THD *thd, char *packet)
+void mysql_stmt_close(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");
+ DBUG_ENTER("mysql_stmt_close");
+ statistic_increment(thd->status_var.com_stmt_close, &LOCK_status);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close")))
DBUG_VOID_RETURN;
@@ -2312,6 +2340,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
DBUG_ENTER("mysql_stmt_get_longdata");
+ statistic_increment(thd->status_var.com_stmt_send_long_data, &LOCK_status);
#ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */
if ((ulong) (packet_end - packet) < MYSQL_LONG_DATA_HEADER)
@@ -2334,7 +2363,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
if (param_number >= stmt->param_count)
{
/* Error will be sent in execute call */
- stmt->state= Item_arena::ERROR;
+ stmt->state= Query_arena::ERROR;
stmt->last_errno= ER_WRONG_ARGUMENTS;
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
"mysql_stmt_send_long_data");
@@ -2350,7 +2379,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
if (param->set_longdata(thd->extra_data, thd->extra_length))
#endif
{
- stmt->state= Item_arena::ERROR;
+ stmt->state= Query_arena::ERROR;
stmt->last_errno= ER_OUTOFMEMORY;
sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0);
}
@@ -2359,7 +2388,9 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
Prepared_statement::Prepared_statement(THD *thd_arg)
- :Statement(thd_arg),
+ :Statement(INITIALIZED, ++thd_arg->statement_id_counter,
+ thd_arg->variables.query_alloc_block_size,
+ thd_arg->variables.query_prealloc_size),
thd(thd_arg),
param_array(0),
param_count(0),
@@ -2368,10 +2399,12 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
*last_error= '\0';
}
+
void Prepared_statement::setup_set_params()
{
/* Setup binary logging */
- if (mysql_bin_log.is_open() && is_update_query(lex->sql_command))
+ if (mysql_bin_log.is_open() && is_update_query(lex->sql_command) ||
+ mysql_log.is_open() || mysql_slow_log.is_open())
{
set_params_from_vars= insert_params_from_vars_with_log;
#ifndef EMBEDDED_LIBRARY
@@ -2396,12 +2429,12 @@ Prepared_statement::~Prepared_statement()
{
if (cursor)
cursor->Cursor::~Cursor();
- free_items(free_list);
+ free_items();
delete lex->result;
}
-Item_arena::Type Prepared_statement::type() const
+Query_arena::Type Prepared_statement::type() const
{
return PREPARED_STATEMENT;
}
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 8fe17198cf0..3880aa428b9 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -164,7 +164,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
ren_table->db, old_alias,
reg_ext);
unpack_filename(name, name);
- if ((table_type=get_table_type(name)) == DB_TYPE_UNKNOWN)
+ if ((table_type=get_table_type(thd, name)) == DB_TYPE_UNKNOWN)
{
my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
if (!skip_error)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 099b7857af8..cf8d7b1b83c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -28,6 +28,8 @@
#include <hash.h>
#include <ft_global.h>
+typedef uint32 cache_rec_length_type;
+
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
"MAYBE_REF","ALL","range","index","fulltext",
"ref_or_null","unique_subquery","index_subquery",
@@ -85,10 +87,9 @@ static void update_depend_map(JOIN *join, ORDER *order);
static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
bool change_list, bool *simple_order);
static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
- List<Item> &fields, bool send_row,
- uint select_options, const char *info,
- Item *having, Procedure *proc,
- SELECT_LEX_UNIT *unit);
+ List<Item> &fields, bool send_row,
+ uint select_options, const char *info,
+ Item *having);
static COND *build_equal_items(THD *thd, COND *cond,
COND_EQUAL *inherited,
List<TABLE_LIST> *join_list,
@@ -136,7 +137,7 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
static enum_nested_loop_state
end_write_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
-static int test_if_group_changed(List<Item_buff> &list);
+static int test_if_group_changed(List<Cached_item> &list);
static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
static int join_read_system(JOIN_TAB *tab);
static int join_read_const(JOIN_TAB *tab);
@@ -580,7 +581,7 @@ JOIN::optimize()
MEMROOT for prepared statements and stored procedures.
*/
- Item_arena *arena= thd->current_arena, backup;
+ Query_arena *arena= thd->current_arena, backup;
if (arena->is_conventional())
arena= 0; // For easier test
else
@@ -812,9 +813,14 @@ JOIN::optimize()
DBUG_RETURN(1);
}
simple_group= 0;
- group_list= remove_const(this, group_list, conds,
- rollup.state == ROLLUP::STATE_NONE,
- &simple_group);
+ {
+ ORDER *old_group_list;
+ group_list= remove_const(this, (old_group_list= group_list), conds,
+ rollup.state == ROLLUP::STATE_NONE,
+ &simple_group);
+ if (old_group_list && !group_list)
+ select_distinct= 0;
+ }
if (!group_list && group)
{
order=0; // The output has only one row
@@ -1220,8 +1226,7 @@ JOIN::exec()
send_row_on_empty_set(),
select_options,
zero_result_cause,
- having, procedure,
- unit);
+ having);
DBUG_VOID_RETURN;
}
@@ -1430,7 +1435,7 @@ JOIN::exec()
DBUG_VOID_RETURN;
}
end_read_record(&curr_join->join_tab->read_record);
- curr_join->const_tables= curr_join->tables; // Mark free for join_free()
+ curr_join->const_tables= curr_join->tables; // Mark free for cleanup()
curr_join->join_tab[0].table= 0; // Table is freed
// No sum funcs anymore
@@ -1660,9 +1665,9 @@ JOIN::exec()
*/
int
-JOIN::cleanup()
+JOIN::destroy()
{
- DBUG_ENTER("JOIN::cleanup");
+ DBUG_ENTER("JOIN::destroy");
select_lex->join= 0;
if (tmp_join)
@@ -1677,12 +1682,11 @@ JOIN::cleanup()
}
tmp_join->tmp_join= 0;
tmp_table_param.copy_field=0;
- DBUG_RETURN(tmp_join->cleanup());
+ DBUG_RETURN(tmp_join->destroy());
}
cond_equal= 0;
- lock=0; // It's faster to unlock later
- join_free(1);
+ cleanup(1);
if (exec_tmp_table1)
free_tmp_table(thd, exec_tmp_table1);
if (exec_tmp_table2)
@@ -1690,18 +1694,21 @@ JOIN::cleanup()
delete select;
delete_dynamic(&keyuse);
delete procedure;
- for (SELECT_LEX_UNIT *lex_unit= select_lex->first_inner_unit();
- lex_unit != 0;
- lex_unit= lex_unit->next_unit())
- {
- error|= lex_unit->cleanup();
- }
DBUG_RETURN(error);
}
/************************* Cursor ******************************************/
-
+
+Cursor::Cursor(THD *thd)
+ :Query_arena(&main_mem_root, INITIALIZED),
+ join(0), unit(0)
+{
+ /* We will overwrite it at open anyway. */
+ init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+}
+
+
void
Cursor::init_from_thd(THD *thd)
{
@@ -1808,6 +1815,7 @@ Cursor::fetch(ulong num_rows)
THD *thd= join->thd;
JOIN_TAB *join_tab= join->join_tab + join->const_tables;
enum_nested_loop_state error= NESTED_LOOP_OK;
+ Query_arena backup_arena;
DBUG_ENTER("Cursor::fetch");
DBUG_PRINT("enter",("rows: %lu", num_rows));
@@ -1819,7 +1827,7 @@ Cursor::fetch(ulong num_rows)
thd->lock= lock;
thd->query_id= query_id;
/* save references to memory, allocated during fetch */
- thd->set_n_backup_item_arena(this, &thd->stmt_backup);
+ thd->set_n_backup_item_arena(this, &backup_arena);
join->fetch_limit+= num_rows;
@@ -1835,7 +1843,7 @@ Cursor::fetch(ulong num_rows)
ha_release_temporary_latches(thd);
#endif
- thd->restore_backup_item_arena(this, &thd->stmt_backup);
+ thd->restore_backup_item_arena(this, &backup_arena);
DBUG_ASSERT(thd->free_list == 0);
reset_thd(thd);
@@ -1868,17 +1876,14 @@ Cursor::close()
THD *thd= join->thd;
DBUG_ENTER("Cursor::close");
- join->join_free(0);
+ /*
+ In case of UNIONs JOIN is freed inside of unit->cleanup(),
+ otherwise in select_lex->cleanup().
+ */
if (unit)
- {
- /* In case of UNIONs JOIN is freed inside unit->cleanup() */
- unit->cleanup();
- }
+ (void) unit->cleanup();
else
- {
- join->cleanup();
- delete join;
- }
+ (void) join->select_lex->cleanup();
{
/* XXX: Another hack: closing tables used in the cursor */
DBUG_ASSERT(lock || open_tables || derived_tables);
@@ -1897,8 +1902,7 @@ Cursor::close()
}
join= 0;
unit= 0;
- free_items(free_list);
- free_list= 0;
+ free_items();
/*
Must be last, as some memory might be allocated for free purposes,
like in free_tmp_table() (TODO: fix this issue)
@@ -2055,8 +2059,7 @@ err:
if (free_join)
{
thd->proc_info="end";
- err= join->cleanup();
- delete join;
+ err= select_lex->cleanup();
DBUG_RETURN(err || thd->net.report_error);
}
DBUG_RETURN(join->error);
@@ -2158,7 +2161,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if (*s->on_expr_ref)
{
/* s is the only inner table of an outer join */
- if (!table->file->records)
+ if (!table->file->records && !embedding)
{ // Empty table
s->dependent= 0; // Ignore LEFT JOIN depend.
set_position(join,const_count++,s,(KEYUSE*) 0);
@@ -5889,29 +5892,68 @@ void JOIN_TAB::cleanup()
}
+void JOIN::join_free(bool full)
+{
+ SELECT_LEX_UNIT *unit;
+ SELECT_LEX *sl;
+ DBUG_ENTER("JOIN::join_free");
+
+ /*
+ Optimization: if not EXPLAIN and we are done with the JOIN,
+ free all tables.
+ */
+ full= full || (!select_lex->uncacheable && !thd->lex->describe);
+
+ cleanup(full);
+
+ for (unit= select_lex->first_inner_unit(); unit; unit= unit->next_unit())
+ for (sl= unit->first_select_in_union(); sl; sl= sl->next_select())
+ {
+ JOIN *join= sl->join;
+ if (join)
+ join->join_free(full);
+ }
+
+ /*
+ We are not using tables anymore
+ Unlock all tables. We may be in an INSERT .... SELECT statement.
+ */
+ if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
+ !select_lex->subquery_in_having &&
+ (select_lex == (thd->lex->unit.fake_select_lex ?
+ thd->lex->unit.fake_select_lex : &thd->lex->select_lex)))
+ {
+ /*
+ TODO: unlock tables even if the join isn't top level select in the
+ tree.
+ */
+ mysql_unlock_read_tables(thd, lock); // Don't free join->lock
+ lock= 0;
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
/*
Free resources of given join
SYNOPSIS
- JOIN::join_free()
+ JOIN::cleanup()
fill - true if we should free all resources, call with full==1 should be
last, before it this function can be called with full==0
NOTE: with subquery this function definitely will be called several times,
but even for simple query it can be called several times.
*/
-void
-JOIN::join_free(bool full)
-{
- JOIN_TAB *tab,*end;
- DBUG_ENTER("JOIN::join_free");
- full= full || (!select_lex->uncacheable &&
- !thd->lex->subqueries &&
- !thd->lex->describe); // do not cleanup too early on EXPLAIN
+void JOIN::cleanup(bool full)
+{
+ DBUG_ENTER("JOIN::cleanup");
if (table)
{
+ JOIN_TAB *tab,*end;
/*
Only a sorted table may be cached. This sorted table is always the
first non const table in join->table
@@ -5922,16 +5964,6 @@ JOIN::join_free(bool full)
filesort_free_buffers(table[const_tables]);
}
- for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit;
- unit= unit->next_unit())
- {
- JOIN *join;
- for (SELECT_LEX *sl= unit->first_select_in_union(); sl;
- sl= sl->next_select())
- if ((join= sl->join))
- join->join_free(full);
- }
-
if (full)
{
for (tab= join_tab, end= tab+tables; tab != end; tab++)
@@ -5948,25 +5980,14 @@ JOIN::join_free(bool full)
}
}
}
-
/*
We are not using tables anymore
Unlock all tables. We may be in an INSERT .... SELECT statement.
*/
- if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
- !select_lex->subquery_in_having)
- {
- // TODO: unlock tables even if the join isn't top level select in the tree
- if (select_lex == (thd->lex->unit.fake_select_lex ?
- thd->lex->unit.fake_select_lex : &thd->lex->select_lex))
- {
- mysql_unlock_read_tables(thd, lock); // Don't free join->lock
- lock=0;
- }
- }
-
if (full)
{
+ if (tmp_join)
+ tmp_table_param.copy_field= 0;
group_fields.delete_elements();
/*
We can't call delete_elements() on copy_funcs as this will cause
@@ -6201,8 +6222,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
static int
return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
List<Item> &fields, bool send_row, uint select_options,
- const char *info, Item *having, Procedure *procedure,
- SELECT_LEX_UNIT *unit)
+ const char *info, Item *having)
{
DBUG_ENTER("return_zero_rows");
@@ -6270,7 +6290,7 @@ public:
COND_CMP(Item *a,Item_func *b) :and_level(a),cmp_func(b) {}
};
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class I_List<COND_CMP>;
template class I_List_iterator<COND_CMP>;
template class List<Item_func_match>;
@@ -7064,7 +7084,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
List_iterator_fast<Item_equal> it(cond_equal->current_level);
while ((item_equal= it++))
{
- eliminate_item_equal(cond, cond_equal->upper_levels, item_equal);
+ cond= eliminate_item_equal(cond, cond_equal->upper_levels, item_equal);
}
}
}
@@ -7937,7 +7957,9 @@ Field *create_tmp_field_for_schema(THD *thd, Item *item, TABLE *table)
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field,
- bool group, bool modify_item, uint convert_blob_length)
+ bool group, bool modify_item,
+ bool table_cant_handle_bit_fields,
+ uint convert_blob_length)
{
switch (type) {
case Item::SUM_FUNC_ITEM:
@@ -7952,11 +7974,27 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::DEFAULT_VALUE_ITEM:
{
Item_field *field= (Item_field*) item;
+ if (table_cant_handle_bit_fields && field->field->type() == FIELD_TYPE_BIT)
+ return create_tmp_field_from_item(thd, item, table, copy_func,
+ modify_item, convert_blob_length);
return create_tmp_field_from_field(thd, (*from_field= field->field),
item->name, table,
modify_item ? (Item_field*) item : NULL,
convert_blob_length);
}
+ case Item::REF_ITEM:
+ if ( item->real_item()->type() == Item::FIELD_ITEM)
+ {
+ Item_field *field= (Item_field*) *((Item_ref*)item)->ref;
+ Field *new_field= create_tmp_field_from_field(thd,
+ (*from_field= field->field),
+ item->name, table,
+ NULL,
+ convert_blob_length);
+ if (modify_item)
+ item->set_result_field(new_field);
+ return new_field;
+ }
case Item::FUNC_ITEM:
case Item::COND_ITEM:
case Item::FIELD_AVG_ITEM:
@@ -7968,7 +8006,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::REAL_ITEM:
case Item::DECIMAL_ITEM:
case Item::STRING_ITEM:
- case Item::REF_ITEM:
case Item::NULL_ITEM:
case Item::VARBIN_ITEM:
return create_tmp_field_from_item(thd, item, table, copy_func, modify_item,
@@ -8160,6 +8197,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
Field *new_field=
create_tmp_field(thd, table, arg, arg->type(), &copy_func,
tmp_from_field, group != 0,not_all_columns,
+ group || distinct,
param->convert_blob_length);
if (!new_field)
goto err; // Should be OOM
@@ -8207,7 +8245,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
create_tmp_field_for_schema(thd, item, table) :
create_tmp_field(thd, table, item, type, &copy_func,
tmp_from_field, group != 0,
- not_all_columns || group !=0,
+ not_all_columns || group != 0, 0,
param->convert_blob_length);
if (!new_field)
@@ -8345,6 +8383,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
else
field->move_field((char*) pos,(uchar*) 0,0);
+ if (field->type() == FIELD_TYPE_BIT)
+ {
+ /* We have to reserve place for extra bits among null bits */
+ ((Field_bit*) field)->set_bit_ptr(null_flags + null_count / 8,
+ null_count & 7);
+ null_count+= (field->field_length & 7);
+ }
field->reset();
if (from_field[i])
{ /* Not a table Item */
@@ -11587,7 +11632,7 @@ used_blob_length(CACHE_FIELD **ptr)
static bool
store_record_in_cache(JOIN_CACHE *cache)
{
- ulong length;
+ cache_rec_length_type length;
uchar *pos;
CACHE_FIELD *copy,*end_field;
bool last_record;
@@ -11632,9 +11677,9 @@ store_record_in_cache(JOIN_CACHE *cache)
end > str && end[-1] == ' ' ;
end--) ;
length=(uint) (end-str);
- memcpy(pos+1,str,length);
- *pos=(uchar) length;
- pos+=length+1;
+ memcpy(pos+sizeof(length), str, length);
+ memcpy_fixed(pos, &length, sizeof(length));
+ pos+= length+sizeof(length);
}
else
{
@@ -11668,7 +11713,7 @@ static void
read_cached_record(JOIN_TAB *tab)
{
uchar *pos;
- uint length;
+ cache_rec_length_type length;
bool last_record;
CACHE_FIELD *copy,*end_field;
@@ -11697,9 +11742,10 @@ read_cached_record(JOIN_TAB *tab)
{
if (copy->strip)
{
- memcpy(copy->str,pos+1,length=(uint) *pos);
- memset(copy->str+length,' ',copy->length-length);
- pos+=1+length;
+ memcpy_fixed(&length, pos, sizeof(length));
+ memcpy(copy->str, pos+sizeof(length), length);
+ memset(copy->str+length, ' ', copy->length-length);
+ pos+= sizeof(length)+length;
}
else
{
@@ -11736,10 +11782,12 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref)
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
for (store_key **copy=ref->key_copy ; *copy ; copy++)
{
- if ((*copy)->copy())
+ int res;
+ if ((res= (*copy)->copy()))
{
thd->count_cuted_fields= save_count_cuted_fields;
- return 1; // Something went wrong
+ if ((res= res & 1))
+ return res; // Something went wrong
}
}
thd->count_cuted_fields= save_count_cuted_fields;
@@ -11778,11 +11826,11 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref)
ref_pointer_array.
RETURN
- 0 if OK
- 1 if error occurred
+ FALSE if OK
+ TRUE if error occurred
*/
-static int
+static bool
find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
ORDER *order, List<Item> &fields, List<Item> &all_fields,
bool is_group_field)
@@ -11799,13 +11847,13 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
order_item->full_name(), thd->where);
- return 1;
+ return TRUE;
}
order->item= ref_pointer_array + count - 1;
order->in_field_list= 1;
order->counter= count;
order->counter_used= 1;
- return 0;
+ return FALSE;
}
/* Lookup the current GROUP/ORDER field in the SELECT clause. */
uint counter;
@@ -11813,7 +11861,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
select_item= find_item_in_list(order_item, fields, &counter,
REPORT_EXCEPT_NOT_FOUND, &unaliased);
if (!select_item)
- return 1; /* Some error occured. */
+ return TRUE; /* The item is not unique, or some other error occured. */
/* Check whether the resolved field is not ambiguos. */
@@ -11827,7 +11875,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
*/
if (unaliased && !order_item->fixed && order_item->fix_fields(thd, tables,
order->item))
- return 1;
+ return TRUE;
/* Lookup the current GROUP field in the FROM clause. */
order_item_type= order_item->type();
@@ -11867,27 +11915,42 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
{
order->item= ref_pointer_array + counter;
order->in_field_list=1;
- return 0;
+ return FALSE;
}
+ else
+ /*
+ There is a field with the same name in the FROM clause. This is the field
+ that will be chosen. In this case we issue a warning so the user knows
+ that the field from the FROM clause overshadows the column reference from
+ the SELECT list.
+ */
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
+ ER(ER_NON_UNIQ_ERROR), from_field->field_name,
+ current_thd->where);
}
order->in_field_list=0;
/*
+ The call to order_item->fix_fields() means that here we resolve 'order_item'
+ to a column from a table in the list 'tables', or to a column in some outer
+ query. Exactly because of the second case we come to this point even if
+ (select_item == not_found_item), inspite of that fix_fields() calls
+ find_item_in_list() one more time.
+
We check order_item->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 (!order_item->fixed &&
(order_item->fix_fields(thd, tables, order->item) ||
(order_item= *order->item)->check_cols(1) ||
thd->is_fatal_error))
- return 1; // Wrong field
+ return TRUE; /* Wrong field. */
+
uint el= all_fields.elements;
- all_fields.push_front(order_item); // Add new field to field list
+ all_fields.push_front(order_item); /* Add new field to field list. */
ref_pointer_array[el]= order_item;
order->item= ref_pointer_array + el;
- return 0;
+ return FALSE;
}
@@ -12274,7 +12337,7 @@ alloc_group_fields(JOIN *join,ORDER *group)
{
for (; group ; group=group->next)
{
- Item_buff *tmp=new_Item_buff(join->thd, *group->item);
+ Cached_item *tmp=new_Cached_item(join->thd, *group->item);
if (!tmp || join->group_fields.push_front(tmp))
return TRUE;
}
@@ -12285,12 +12348,12 @@ alloc_group_fields(JOIN *join,ORDER *group)
static int
-test_if_group_changed(List<Item_buff> &list)
+test_if_group_changed(List<Cached_item> &list)
{
DBUG_ENTER("test_if_group_changed");
- List_iterator<Item_buff> li(list);
+ List_iterator<Cached_item> li(list);
int idx= -1,i;
- Item_buff *buff;
+ Cached_item *buff;
for (i=(int) list.elements-1 ; (buff=li++) ; i--)
{
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 5351bbb13d3..6d33ae2f978 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -178,7 +178,7 @@ class JOIN :public Sql_alloc
table_map const_table_map,found_const_table_map,outer_join;
ha_rows send_records,found_records,examined_rows,row_limit, select_limit;
/*
- Used to fetch no more than given amount of rows per one
+ Used to fetch no more than given amount of rows per one
fetch operation of server side cursor.
The value is checked in end_send and end_send_group in fashion, similar
to offset_limit_cnt:
@@ -190,7 +190,7 @@ class JOIN :public Sql_alloc
POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
double best_read;
List<Item> *fields;
- List<Item_buff> group_fields, group_fields_cache;
+ List<Cached_item> group_fields, group_fields_cache;
TABLE *tmp_table;
// used to store 2 possible tmp table of SELECT
TABLE *exec_tmp_table1, *exec_tmp_table2;
@@ -325,7 +325,7 @@ class JOIN :public Sql_alloc
int optimize();
int reinit();
void exec();
- int cleanup();
+ int destroy();
void restore_tmp();
bool alloc_func_list();
bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
@@ -349,7 +349,15 @@ class JOIN :public Sql_alloc
int rollup_send_data(uint idx);
int rollup_write_data(uint idx, TABLE *table);
bool test_in_subselect(Item **where);
+ /*
+ Release memory and, if possible, the open tables held by this execution
+ plan (and nested plans). It's used to release some tables before
+ the end of execution in order to increase concurrency and reduce
+ memory consumption.
+ */
void join_free(bool full);
+ /* Cleanup this JOIN, possibly for reuse */
+ void cleanup(bool full);
void clear();
bool save_join_tab();
bool send_row_on_empty_set()
@@ -370,8 +378,9 @@ class JOIN :public Sql_alloc
statement for many cursors.
*/
-class Cursor: public Sql_alloc, public Item_arena
+class Cursor: public Sql_alloc, public Query_arena
{
+ MEM_ROOT main_mem_root;
JOIN *join;
SELECT_LEX_UNIT *unit;
@@ -396,7 +405,7 @@ public:
void close();
void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; }
- Cursor() :Item_arena(TRUE), join(0), unit(0) {}
+ Cursor(THD *thd);
~Cursor();
};
@@ -447,6 +456,7 @@ class store_key :public Sql_alloc
char *null_ptr;
char err;
public:
+ enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV };
store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length)
:null_ptr(null),err(0)
{
@@ -462,7 +472,7 @@ class store_key :public Sql_alloc
ptr, (uchar*) null, 1);
}
virtual ~store_key() {} /* Not actually needed */
- virtual bool copy()=0;
+ virtual enum store_key_result copy()=0;
virtual const char *name() const=0;
};
@@ -483,10 +493,10 @@ class store_key_field: public store_key
copy_field.set(to_field,from_field,0);
}
}
- bool copy()
+ enum store_key_result copy()
{
copy_field.do_copy(&copy_field);
- return err != 0;
+ return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK;
}
const char *name() const { return field_name; }
};
@@ -503,9 +513,11 @@ public:
null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
&err : NullS, length), item(item_arg)
{}
- bool copy()
+ enum store_key_result copy()
{
- return item->save_in_field_no_warnings(to_field, 1) || err != 0;
+ int res= item->save_in_field(to_field, 1);
+ return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res);
+
}
const char *name() const { return "func"; }
};
@@ -523,15 +535,19 @@ public:
&err : NullS, length, item_arg), inited(0)
{
}
- bool copy()
+ enum store_key_result copy()
{
+ int res;
if (!inited)
{
inited=1;
- if (item->save_in_field(to_field, 1))
- err= 1;
+ if ((res= item->save_in_field(to_field, 1)))
+ {
+ if (!err)
+ err= res;
+ }
}
- return err != 0;
+ return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err);
}
const char *name() const { return "const"; }
};
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 1e34f32184a..12025c82da6 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -348,7 +348,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
table_list->table_name));
/* Only one table for now, but VIEW can involve several tables */
- if (open_and_lock_tables(thd, table_list))
+ if (open_normal_and_derived_tables(thd, table_list))
{
DBUG_RETURN(TRUE);
}
@@ -448,25 +448,32 @@ bool mysqld_show_create_db(THD *thd, char *dbname,
DBUG_RETURN(TRUE);
}
#endif
-
- (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
- length=unpack_dirname(path,path); // Convert if not unix
- found_libchar= 0;
- if (length && path[length-1] == FN_LIBCHAR)
+ if (!my_strcasecmp(system_charset_info, dbname,
+ information_schema_name.str))
{
- found_libchar= 1;
- path[length-1]=0; // remove ending '\'
+ dbname= information_schema_name.str;
+ create.default_table_charset= system_charset_info;
}
- if (access(path,F_OK))
+ else
{
- my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
- DBUG_RETURN(TRUE);
+ (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
+ length=unpack_dirname(path,path); // Convert if not unix
+ found_libchar= 0;
+ if (length && path[length-1] == FN_LIBCHAR)
+ {
+ found_libchar= 1;
+ path[length-1]=0; // remove ending '\'
+ }
+ if (access(path,F_OK))
+ {
+ my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
+ DBUG_RETURN(TRUE);
+ }
+ if (found_libchar)
+ path[length-1]= FN_LIBCHAR;
+ strmov(path+length, MY_DB_OPT_FILE);
+ load_db_opt(thd, path, &create);
}
- if (found_libchar)
- path[length-1]= FN_LIBCHAR;
- strmov(path+length, MY_DB_OPT_FILE);
- load_db_opt(thd, path, &create);
-
List<Item> field_list;
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
field_list.push_back(new Item_empty_string("Create Database",1024));
@@ -540,8 +547,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
DBUG_ENTER("mysqld_list_fields");
DBUG_PRINT("enter",("table: %s",table_list->table_name));
- table_list->lock_type= TL_UNLOCK;
- if (open_and_lock_tables(thd, table_list))
+ if (open_normal_and_derived_tables(thd, table_list))
DBUG_VOID_RETURN;
table= table_list->table;
@@ -1096,7 +1102,7 @@ public:
char *query;
};
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class I_List<thread_info>;
#endif
@@ -1945,7 +1951,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
bool res;
lex->all_selects_list= lsel;
- res= open_and_lock_tables(thd, show_table_list);
+ res= open_normal_and_derived_tables(thd, show_table_list);
if (schema_table->process_table(thd, show_table_list,
table, res, show_table_list->db,
show_table_list->alias))
@@ -2050,7 +2056,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
show_table_list->lock_type= lock_type;
lex->all_selects_list= &sel;
lex->derived_tables= 0;
- res= open_and_lock_tables(thd, show_table_list);
+ res= open_normal_and_derived_tables(thd, show_table_list);
if (schema_table->process_table(thd, show_table_list, table,
res, base_name,
show_table_list->alias))
@@ -2646,6 +2652,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
restore_record(table, s->default_values);
if (!wild || !wild[0] || !wild_compare(sp_name, wild, 0))
{
+ int enum_idx= proc_table->field[5]->val_int();
table->field[3]->store(sp_name, strlen(sp_name), cs);
get_field(thd->mem_root, proc_table->field[3], &tmp_string);
table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs);
@@ -2667,10 +2674,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
table->field[10]->store("SQL", 3, cs);
get_field(thd->mem_root, proc_table->field[6], &tmp_string);
table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs);
- if (proc_table->field[5]->val_int() == SP_CONTAINS_SQL)
- {
- table->field[12]->store("CONTAINS SQL", 12 , cs);
- }
+ table->field[12]->store(sp_data_access_name[enum_idx].str,
+ sp_data_access_name[enum_idx].length , cs);
get_field(thd->mem_root, proc_table->field[7], &tmp_string);
table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs);
bzero((char *)&time, sizeof(time));
@@ -3874,7 +3879,7 @@ ST_SCHEMA_TABLE schema_tables[]=
};
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List_iterator_fast<char>;
template class List<char>;
#endif
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 8a29c481dc1..553a853bede 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -39,6 +39,8 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
static bool prepare_blob_field(THD *thd, create_field *sql_field);
+static bool check_engine(THD *thd, const char *table_name,
+ enum db_type *new_engine);
/*
@@ -254,21 +256,23 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
build_table_path(path, sizeof(path), db, alias, reg_ext);
}
if (drop_temporary ||
- (access(path,F_OK) &&
- ha_create_table_from_engine(thd,db,alias,TRUE)) ||
+ (access(path,F_OK) &&
+ ha_create_table_from_engine(thd,db,alias)) ||
(!drop_view && mysql_frm_type(path) != FRMTYPE_TABLE))
{
+ // Table was not found on disk and table can't be created from engine
if (if_exists)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
table->table_name);
else
- error= 1;
+ error= 1;
+
}
else
{
char *end;
- db_type table_type= get_table_type(path);
+ db_type table_type= get_table_type(thd, path);
*(end=fn_ext(path))=0; // Remove extension for delete
error= ha_delete_table(thd, table_type, path, table->table_name,
!dont_log_query);
@@ -1490,7 +1494,6 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
KEY *key_info_buffer;
handler *file;
bool error= TRUE;
- enum db_type new_db_type;
DBUG_ENTER("mysql_create_table");
/* Check for duplicate fields and check type of table to create */
@@ -1500,16 +1503,8 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
MYF(0));
DBUG_RETURN(TRUE);
}
- if ((new_db_type= ha_checktype(create_info->db_type)) !=
- create_info->db_type)
- {
- create_info->db_type= new_db_type;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_USING_OTHER_HANDLER,
- ER(ER_WARN_USING_OTHER_HANDLER),
- ha_get_storage_engine(new_db_type),
- table_name);
- }
+ if (check_engine(thd, table_name, &create_info->db_type))
+ DBUG_RETURN(TRUE);
db_options= create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
@@ -1611,15 +1606,14 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
{
bool create_if_not_exists =
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
- if (!ha_create_table_from_engine(thd, db, table_name,
- create_if_not_exists))
+ if (ha_table_exists_in_engine(thd, db, table_name))
{
- DBUG_PRINT("info", ("Table already existed in handler"));
+ DBUG_PRINT("info", ("Table with same name already existed in handler"));
if (create_if_not_exists)
{
- create_info->table_existed= 1; // Mark that table existed
- error= FALSE;
+ create_info->table_existed= 1; // Mark that table existed
+ error= FALSE;
}
else
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
@@ -1740,7 +1734,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
field=item->tmp_table_field(&tmp_table);
else
field=create_tmp_field(thd, &tmp_table, item, item->type(),
- (Item ***) 0, &tmp_field,0,0,0);
+ (Item ***) 0, &tmp_field, 0, 0, 0, 0);
if (!field ||
!(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
((Item_field *)item)->field :
@@ -3125,16 +3119,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
old_db_type= table->s->db_type;
if (create_info->db_type == DB_TYPE_DEFAULT)
create_info->db_type= old_db_type;
- if ((new_db_type= ha_checktype(create_info->db_type)) !=
- create_info->db_type)
- {
- create_info->db_type= new_db_type;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_USING_OTHER_HANDLER,
- ER(ER_WARN_USING_OTHER_HANDLER),
- ha_get_storage_engine(new_db_type),
- new_name);
- }
+ if (check_engine(thd, new_name, &create_info->db_type))
+ DBUG_RETURN(TRUE);
+ new_db_type= create_info->db_type;
if (create_info->row_type == ROW_TYPE_NOT_USED)
create_info->row_type= table->s->row_type;
@@ -4132,3 +4119,24 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
table->table=0;
DBUG_RETURN(TRUE);
}
+
+static bool check_engine(THD *thd, const char *table_name,
+ enum db_type *new_engine)
+{
+ enum db_type req_engine= *new_engine;
+ bool no_substitution=
+ test(thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION);
+ if ((*new_engine=
+ ha_checktype(thd, req_engine, no_substitution, 1)) == DB_TYPE_UNKNOWN)
+ return TRUE;
+
+ if (req_engine != *new_engine)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_USING_OTHER_HANDLER,
+ ER(ER_WARN_USING_OTHER_HANDLER),
+ ha_get_storage_engine(*new_engine),
+ table_name);
+ }
+ return FALSE;
+}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 912636b6cf3..6e307dda5be 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -274,7 +274,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
all collations together for UNION.
*/
List_iterator_fast<Item> tp(types);
- Item_arena *arena= thd->current_arena;
+ Query_arena *arena= thd->current_arena;
Item *type;
while ((type= tp++))
@@ -308,7 +308,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (!item_list.elements)
{
Field **field;
- Item_arena *tmp_arena,backup;
+ Query_arena *tmp_arena,backup;
tmp_arena= thd->change_arena_if_needed(&backup);
for (field= table->field; *field; field++)
@@ -553,7 +553,6 @@ bool st_select_lex_unit::exec()
bool st_select_lex_unit::cleanup()
{
int error= 0;
- JOIN *join;
DBUG_ENTER("st_select_lex_unit::cleanup");
if (cleaned)
@@ -572,29 +571,17 @@ bool st_select_lex_unit::cleanup()
}
for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
+ error|= sl->cleanup();
+
+ if (fake_select_lex)
{
- if ((join= sl->join))
- {
- error|= sl->join->cleanup();
- delete join;
- }
- else
+ JOIN *join;
+ if ((join= fake_select_lex->join))
{
- // it can be DO/SET with subqueries
- for (SELECT_LEX_UNIT *lex_unit= sl->first_inner_unit();
- lex_unit != 0;
- lex_unit= lex_unit->next_unit())
- {
- error|= lex_unit->cleanup();
- }
+ join->tables_list= 0;
+ join->tables= 0;
}
- }
- if (fake_select_lex && (join= fake_select_lex->join))
- {
- join->tables_list= 0;
- join->tables= 0;
- error|= join->cleanup();
- delete join;
+ error|= fake_select_lex->cleanup();
}
DBUG_RETURN(error);
@@ -650,3 +637,25 @@ bool st_select_lex_unit::change_result(select_subselect *result,
res= fake_select_lex->join->change_result(result);
return (res);
}
+
+
+bool st_select_lex::cleanup()
+{
+ bool error= FALSE;
+ DBUG_ENTER("st_select_lex::cleanup()");
+
+ if (join)
+ {
+ DBUG_ASSERT((st_select_lex*)join->select_lex == this);
+ error|= join->destroy();
+ delete join;
+ join= 0;
+ }
+ for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ;
+ lex_unit= lex_unit->next_unit())
+ {
+ error|= lex_unit->cleanup();
+ }
+ DBUG_RETURN(error);
+}
+
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 9f0c3260d8f..0b351407c13 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -36,6 +36,61 @@ TYPELIB updatable_views_with_limit_typelib=
/*
+ Make a unique name for an anonymous view column
+ SYNOPSIS
+ target reference to the item for which a new name has to be made
+ item_list list of items within which we should check uniqueness of
+ the created name
+ last_element the last element of the list above
+
+ NOTE
+ Unique names are generated by adding 'My_exp_' to the old name of the
+ column. In case the name that was created this way already exists, we
+ add a numeric postfix to its end (i.e. "1") and increase the number
+ until the name becomes unique. If the generated name is longer than
+ NAME_LEN, it is truncated.
+*/
+
+static void make_unique_view_field_name(Item *target,
+ List<Item> &item_list,
+ Item *last_element)
+{
+ char *name= (target->orig_name ?
+ target->orig_name :
+ target->name);
+ uint name_len;
+ uint attempt= 0;
+ char buff[NAME_LEN+1];
+ for (;; attempt++)
+ {
+ Item *check;
+ List_iterator_fast<Item> itc(item_list);
+ bool ok= TRUE;
+
+ if (attempt)
+ name_len= my_snprintf(buff, NAME_LEN, "My_exp_%d_%s", attempt, name);
+ else
+ name_len= my_snprintf(buff, NAME_LEN, "My_exp_%s", name);
+
+ do
+ {
+ check= itc++;
+ if (check != target &&
+ my_strcasecmp(system_charset_info, buff, check->name) == 0)
+ {
+ ok= FALSE;
+ break;
+ }
+ } while (check != last_element);
+ if (ok)
+ break;
+ }
+
+ target->orig_name= target->name;
+ target->set_name(buff, name_len, system_charset_info);
+}
+
+/*
Creating/altering VIEW procedure
SYNOPSIS
@@ -240,24 +295,36 @@ bool mysql_create_view(THD *thd,
goto err;
}
while ((item= it++, name= nm++))
+ {
item->set_name(name->str, name->length, system_charset_info);
+ item->is_autogenerated_name= FALSE;
+ }
}
/* Test absence of duplicates names */
{
Item *item;
List_iterator_fast<Item> it(select_lex->item_list);
- it++;
while ((item= it++))
{
Item *check;
List_iterator_fast<Item> itc(select_lex->item_list);
+ /* treat underlying fields like set by user names */
+ if (item->real_item()->type() == Item::FIELD_ITEM)
+ item->is_autogenerated_name= FALSE;
while ((check= itc++) && check != item)
{
- if (strcmp(item->name, check->name) == 0)
+ if (my_strcasecmp(system_charset_info, item->name, check->name) == 0)
{
- my_error(ER_DUP_FIELDNAME, MYF(0), item->name);
- DBUG_RETURN(TRUE);
+ if (item->is_autogenerated_name)
+ make_unique_view_field_name(item, select_lex->item_list, item);
+ else if (check->is_autogenerated_name)
+ make_unique_view_field_name(check, select_lex->item_list, item);
+ else
+ {
+ my_error(ER_DUP_FIELDNAME, MYF(0), item->name);
+ DBUG_RETURN(TRUE);
+ }
}
}
}
@@ -579,7 +646,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
For now we assume that tables will not be changed during PS life (it
will be TRUE as far as we make new table cache).
*/
- Item_arena *arena= thd->current_arena, backup;
+ Query_arena *arena= thd->current_arena, backup;
if (arena->is_conventional())
arena= 0;
else
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 892d2516808..360bc421965 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -52,7 +52,7 @@ const LEX_STRING null_lex_str={0,0};
ER_WARN_DEPRECATED_SYNTAX, \
ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B));
-#define TEST_ASSERT(A) \
+#define YYERROR_UNLESS(A) \
if (!(A)) \
{ \
yyerror(ER(ER_SYNTAX_ERROR)); \
@@ -914,7 +914,7 @@ deallocate:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
- if (thd->command == COM_PREPARE)
+ if (thd->command == COM_STMT_PREPARE)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
@@ -939,7 +939,7 @@ prepare:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
- if (thd->command == COM_PREPARE)
+ if (thd->command == COM_STMT_PREPARE)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
@@ -974,7 +974,7 @@ execute:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
- if (thd->command == COM_PREPARE)
+ if (thd->command == COM_STMT_PREPARE)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
@@ -4107,7 +4107,10 @@ select_item:
if (add_item_to_list(YYTHD, $2))
YYABORT;
if ($4.str)
- $2->set_name($4.str,$4.length,system_charset_info);
+ {
+ $2->set_name($4.str, $4.length, system_charset_info);
+ $2->is_autogenerated_name= FALSE;
+ }
else if (!$2->name) {
char *str = $1;
if (str[-1] == '`')
@@ -4913,9 +4916,12 @@ udf_expr:
remember_name expr remember_end select_alias
{
if ($4.str)
- $2->set_name($4.str,$4.length,system_charset_info);
+ {
+ $2->set_name($4.str, $4.length, system_charset_info);
+ $2->is_autogenerated_name= FALSE;
+ }
else
- $2->set_name($1,(uint) ($3 - $1), YYTHD->charset());
+ $2->set_name($1, (uint) ($3 - $1), YYTHD->charset());
$$= $2;
}
;
@@ -5094,7 +5100,7 @@ table_ref:
;
join_table_list:
- derived_table_list { TEST_ASSERT($$=$1); }
+ derived_table_list { YYERROR_UNLESS($$=$1); }
;
/* Warning - may return NULL in case of incomplete SELECT */
@@ -5102,41 +5108,41 @@ derived_table_list:
table_ref { $$=$1; }
| derived_table_list ',' table_ref
{
- TEST_ASSERT($1 && ($$=$3));
+ YYERROR_UNLESS($1 && ($$=$3));
}
;
join_table:
- table_ref normal_join table_ref { TEST_ASSERT($1 && ($$=$3)); }
+ table_ref normal_join table_ref { YYERROR_UNLESS($1 && ($$=$3)); }
| table_ref STRAIGHT_JOIN table_factor
- { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; }
+ { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; }
| table_ref normal_join table_ref ON expr
- { TEST_ASSERT($1 && ($$=$3)); add_join_on($3,$5); }
+ { YYERROR_UNLESS($1 && ($$=$3)); add_join_on($3,$5); }
| table_ref STRAIGHT_JOIN table_factor ON expr
- { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; add_join_on($3,$5); }
+ { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; add_join_on($3,$5); }
| table_ref normal_join table_ref
USING
{
SELECT_LEX *sel= Select;
- TEST_ASSERT($1 && $3);
+ YYERROR_UNLESS($1 && $3);
sel->save_names_for_using_list($1, $3);
}
'(' using_list ')'
{ add_join_on($3,$7); $$=$3; }
| table_ref LEFT opt_outer JOIN_SYM table_ref ON expr
- { TEST_ASSERT($1 && $5); add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
+ { YYERROR_UNLESS($1 && $5); add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| table_ref LEFT opt_outer JOIN_SYM table_factor
{
SELECT_LEX *sel= Select;
- TEST_ASSERT($1 && $5);
+ YYERROR_UNLESS($1 && $5);
sel->save_names_for_using_list($1, $5);
}
USING '(' using_list ')'
{ add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
{
- TEST_ASSERT($1 && $6);
+ YYERROR_UNLESS($1 && $6);
add_join_natural($1,$6);
$6->outer_join|=JOIN_TYPE_LEFT;
$$=$6;
@@ -5144,7 +5150,7 @@ join_table:
| table_ref RIGHT opt_outer JOIN_SYM table_ref ON expr
{
LEX *lex= Lex;
- TEST_ASSERT($1 && $5);
+ YYERROR_UNLESS($1 && $5);
if (!($$= lex->current_select->convert_right_join()))
YYABORT;
add_join_on($$, $7);
@@ -5152,7 +5158,7 @@ join_table:
| table_ref RIGHT opt_outer JOIN_SYM table_factor
{
SELECT_LEX *sel= Select;
- TEST_ASSERT($1 && $5);
+ YYERROR_UNLESS($1 && $5);
sel->save_names_for_using_list($1, $5);
}
USING '(' using_list ')'
@@ -5164,14 +5170,14 @@ join_table:
}
| table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
{
- TEST_ASSERT($1 && $6);
+ YYERROR_UNLESS($1 && $6);
add_join_natural($6,$1);
LEX *lex= Lex;
if (!($$= lex->current_select->convert_right_join()))
YYABORT;
}
| table_ref NATURAL JOIN_SYM table_factor
- { TEST_ASSERT($1 && ($$=$4)); add_join_natural($1,$4); };
+ { YYERROR_UNLESS($1 && ($$=$4)); add_join_natural($1,$4); };
normal_join:
@@ -5200,7 +5206,7 @@ table_factor:
sel->add_joined_table($$);
}
| '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}'
- { TEST_ASSERT($3 && $7); add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
+ { YYERROR_UNLESS($3 && $7); add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
| select_derived_init get_select_lex select_derived2
{
LEX *lex= Lex;
@@ -5691,7 +5697,8 @@ procedure_item:
if (add_proc_to_list(lex->thd, $2))
YYABORT;
if (!$2->name)
- $2->set_name($1,(uint) ((char*) lex->tok_end - $1), YYTHD->charset());
+ $2->set_name($1,(uint) ((char*) lex->tok_end - $1),
+ YYTHD->charset());
}
;
@@ -6113,9 +6120,24 @@ insert_update_elem:
simple_ident_nospvar equal expr_or_default
{
LEX *lex= Lex;
+ uint8 tmp= MY_ITEM_PREFER_1ST_TABLE;
if (lex->update_list.push_back($1) ||
lex->value_list.push_back($3))
YYABORT;
+ /*
+ INSERT INTO a1(a) SELECT b1.a FROM b1 ON DUPLICATE KEY
+ UPDATE a= a + b1.b
+
+ Set MY_ITEM_PREFER_1ST_TABLE flag to $1 and $3 items
+ to prevent find_field_in_tables() doing further item searching
+ if it finds item occurence in first table in insert_table_list.
+ This allows to avoid ambiguity in resolving 'a' field in
+ example above.
+ */
+ $1->walk(&Item::set_flags_processor,
+ (byte *) &tmp);
+ $3->walk(&Item::set_flags_processor,
+ (byte *) &tmp);
};
opt_low_priority:
@@ -6902,7 +6924,7 @@ param_marker:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
- if (thd->command == COM_PREPARE)
+ if (thd->command == COM_STMT_PREPARE)
{
Item_param *item= new Item_param((uint) (lex->tok_start -
(uchar *) thd->query));
@@ -8731,21 +8753,21 @@ xa: XA_SYM begin_or_start xid opt_join_or_resume
xid: text_string
{
- TEST_ASSERT($1->length() <= MAXGTRIDSIZE);
+ YYERROR_UNLESS($1->length() <= MAXGTRIDSIZE);
if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
YYABORT;
Lex->xid->set(1L, $1->ptr(), $1->length(), 0, 0);
}
| text_string ',' text_string
{
- TEST_ASSERT($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
+ YYERROR_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
YYABORT;
Lex->xid->set(1L, $1->ptr(), $1->length(), $3->ptr(), $3->length());
}
| text_string ',' text_string ',' ulong_num
{
- TEST_ASSERT($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
+ YYERROR_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
YYABORT;
Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length());
diff --git a/sql/structs.h b/sql/structs.h
index 8f053f20776..03176b47360 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -20,6 +20,8 @@
struct st_table;
class Field;
+#define STRING_WITH_LEN(X) X, (sizeof(X)-1)
+
typedef struct st_lex_string
{
char *str;
diff --git a/sql/table.cc b/sql/table.cc
index 33cee79eb61..6677453969b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -163,7 +163,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5)
share->frm_version= FRM_VER_TRUE_VARCHAR;
- share->db_type= ha_checktype((enum db_type) (uint) *(head+3));
+ share->db_type= ha_checktype(thd,(enum db_type) (uint) *(head+3),0,0);
share->db_create_options= db_create_options=uint2korr(head+30);
share->db_options_in_use= share->db_create_options;
share->mysql_version= uint4korr(head+51);
@@ -1341,8 +1341,8 @@ void append_unescaped(String *res, const char *pos, uint length)
/* Create a .frm file */
-File create_frm(register my_string name, uint reclength, uchar *fileinfo,
- HA_CREATE_INFO *create_info, uint keys)
+File create_frm(THD *thd, register my_string name, uint reclength,
+ uchar *fileinfo, HA_CREATE_INFO *create_info, uint keys)
{
register File file;
ulong length;
@@ -1375,7 +1375,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
fileinfo[1]= 1;
fileinfo[2]= FRM_VER+3+ test(create_info->varchar);
- fileinfo[3]= (uchar) ha_checktype(create_info->db_type);
+ fileinfo[3]= (uchar) ha_checktype(thd,create_info->db_type,0,0);
fileinfo[4]=1;
int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
key_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16;
@@ -1637,7 +1637,7 @@ bool check_column_name(const char *name)
** Get type of table from .frm file
*/
-db_type get_table_type(const char *name)
+db_type get_table_type(THD *thd, const char *name)
{
File file;
uchar head[4];
@@ -1653,7 +1653,7 @@ db_type get_table_type(const char *name)
(head[2] != FRM_VER && head[2] != FRM_VER+1 &&
(head[2] < FRM_VER+3 || head[2] > FRM_VER+4)))
DBUG_RETURN(DB_TYPE_UNKNOWN);
- DBUG_RETURN(ha_checktype((enum db_type) (uint) *(head+3)));
+ DBUG_RETURN(ha_checktype(thd,(enum db_type) (uint) *(head+3),0,0));
}
@@ -1926,7 +1926,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
(check_opt_type == VIEW_CHECK_CASCADED &&
ancestor->check_option))
{
- Item_arena *arena= thd->current_arena, backup;
+ Query_arena *arena= thd->current_arena, backup;
TABLE_LIST *tbl= this;
if (arena->is_conventional())
arena= 0; // For easier test
@@ -2016,7 +2016,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
/* full text function moving to current select */
if (view->select_lex.ftfunc_list->elements)
{
- Item_arena *arena= thd->current_arena, backup;
+ Query_arena *arena= thd->current_arena, backup;
if (arena->is_conventional())
arena= 0; // For easier test
else
@@ -2236,7 +2236,7 @@ const char *Field_iterator_view::name()
** Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<String>;
template class List_iterator<String>;
#endif
diff --git a/sql/unireg.cc b/sql/unireg.cc
index e8aad2fedd0..7f170b3ef87 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -113,7 +113,7 @@ bool mysql_create_frm(THD *thd, my_string file_name,
}
reclength=uint2korr(forminfo+266);
- if ((file=create_frm(file_name, reclength, fileinfo,
+ if ((file=create_frm(thd, file_name, reclength, fileinfo,
create_info, keys)) < 0)
{
my_free((gptr) screen_buff,MYF(0));
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index a4040ed2b90..01ecd63d52b 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -6320,7 +6320,7 @@ uint my_well_formed_len_big5(CHARSET_INFO *cs __attribute__((unused)),
break;
}
}
- return b - b0;
+ return (uint) (b - b0);
}
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 13105df9334..40ecbc33d61 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -433,7 +433,7 @@ skip:
if (nmatch > 0)
{
match[0].beg= 0;
- match[0].end= str- (const uchar*)b-1;
+ match[0].end= (uint) (str- (const uchar*)b-1);
match[0].mblen= match[0].end;
if (nmatch > 1)
diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c
index fd2b0fd8e21..f62cf2db599 100644
--- a/strings/ctype-cp932.c
+++ b/strings/ctype-cp932.c
@@ -5446,7 +5446,7 @@ uint my_well_formed_len_cp932(CHARSET_INFO *cs __attribute__((unused)),
break;
}
}
- return b - b0;
+ return (uint) (b - b0);
}
diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c
index 784293918ed..58caac15256 100644
--- a/strings/ctype-eucjpms.c
+++ b/strings/ctype-eucjpms.c
@@ -8403,14 +8403,14 @@ uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)),
chbeg= (char *) b++;
if (b >= (uchar *) end) /* need more bytes */
- return chbeg - beg; /* unexpected EOL */
+ return (uint) (chbeg - beg); /* unexpected EOL */
if (ch == 0x8E) /* [x8E][xA0-xDF] */
{
if (*b >= 0xA0 && *b <= 0xDF)
continue;
*error=1;
- return chbeg - beg; /* invalid sequence */
+ return (uint) (chbeg - beg); /* invalid sequence */
}
if (ch == 0x8F) /* [x8F][xA1-xFE][xA1-xFE] */
@@ -8419,7 +8419,7 @@ uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)),
if (b >= (uchar*) end)
{
*error= 1;
- return chbeg - beg; /* unexpected EOL */
+ return (uint)(chbeg - beg); /* unexpected EOL */
}
}
@@ -8427,9 +8427,9 @@ uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)),
*b >= 0xA1 && *b <= 0xFE) /* [xA1-xFE][xA1-xFE] */
continue;
*error=1;
- return chbeg - beg; /* invalid sequence */
+ return (uint) (chbeg - beg); /* invalid sequence */
}
- return b - (uchar *) beg;
+ return (uint) (b - (uchar *) beg);
}
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 2d9f8b16bfc..6f171c03845 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -268,7 +268,7 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
pos+= (mblen= my_ismbchar(cs, pos, end)) ? mblen : 1;
length--;
}
- return length ? end+2-start : pos-start;
+ return (uint) (length ? end+2-start : pos-start);
}
@@ -290,7 +290,7 @@ uint my_well_formed_len_mb(CHARSET_INFO *cs, const char *b, const char *e,
b+= mblen;
pos--;
}
- return b - b_start;
+ return (uint) (b - b_start);
}
@@ -329,7 +329,7 @@ uint my_instr_mb(CHARSET_INFO *cs,
if (nmatch)
{
match[0].beg= 0;
- match[0].end= b-b0;
+ match[0].end= (uint) (b-b0);
match[0].mblen= res;
if (nmatch > 1)
{
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 6ed1af846ec..fe514186deb 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -1084,7 +1084,7 @@ ulong my_scan_8bit(CHARSET_INFO *cs, const char *str, const char *end, int sq)
if (*str == '.')
{
for(str++ ; str != end && *str == '0' ; str++);
- return str-str0;
+ return (ulong) (str-str0);
}
return 0;
@@ -1094,7 +1094,7 @@ ulong my_scan_8bit(CHARSET_INFO *cs, const char *str, const char *end, int sq)
if (!my_isspace(cs,*str))
break;
}
- return str-str0;
+ return (ulong) (str-str0);
default:
return 0;
}
@@ -1111,14 +1111,14 @@ void my_fill_8bit(CHARSET_INFO *cs __attribute__((unused)),
uint my_numchars_8bit(CHARSET_INFO *cs __attribute__((unused)),
const char *b, const char *e)
{
- return e-b;
+ return (uint) (e-b);
}
uint my_numcells_8bit(CHARSET_INFO *cs __attribute__((unused)),
const char *b, const char *e)
{
- return e-b;
+ return (uint) (e-b);
}
@@ -1193,7 +1193,7 @@ skip:
if (nmatch > 0)
{
match[0].beg= 0;
- match[0].end= str- (const uchar*)b-1;
+ match[0].end= (uint) (str- (const uchar*)b-1);
match[0].mblen= match[0].end;
if (nmatch > 1)
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 9cd5d6d7981..161f75ca936 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -4615,7 +4615,7 @@ uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)),
break;
}
}
- return b - b0;
+ return (uint) (b - b0);
}
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index eb207c9821f..8bc48b3609d 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -7527,7 +7527,7 @@ static void my_coll_lexem_print_error(MY_COLL_LEXEM *lexem,
{
char tail[30];
size_t len= lexem->end - lexem->prev;
- strmake (tail, lexem->prev, min(len, sizeof(tail)-1));
+ strmake (tail, lexem->prev, (uint) min(len, sizeof(tail)-1));
errstr[errsize-1]= '\0';
my_snprintf(errstr,errsize-1,"%s at '%s'", txt, tail);
}
@@ -7769,7 +7769,7 @@ static int my_coll_rule_parse(MY_COLL_RULE *rule, size_t mitems,
continue;
}
}
- return (size_t) nitems;
+ return (int) nitems;
}
#define MY_MAX_COLL_RULE 128
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 4acd75d7a6f..5844a6e688b 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -229,7 +229,7 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return t_is_prefix ? t-te : ((se-s) - (te-t));
+ return (int) (t_is_prefix ? t-te : ((se-s) - (te-t)));
}
/*
@@ -344,14 +344,14 @@ static int my_strncasecmp_ucs2(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return ( (se-s) - (te-t) );
+ return (int) ( (se-s) - (te-t) );
}
static int my_strcasecmp_ucs2(CHARSET_INFO *cs, const char *s, const char *t)
{
- uint s_len=strlen(s);
- uint t_len=strlen(t);
+ uint s_len= (uint) strlen(s);
+ uint t_len= (uint) strlen(t);
uint len = (s_len > t_len) ? s_len : t_len;
return my_strncasecmp_ucs2(cs, s, t, len);
}
@@ -386,7 +386,7 @@ static int my_strnxfrm_ucs2(CHARSET_INFO *cs,
dst+=res;
}
if (dst < de)
- cs->cset->fill(cs, (char*) dst, de - dst, ' ');
+ cs->cset->fill(cs, (char*) dst, (uint) (de - dst), ' ');
return dstlen;
}
@@ -1370,7 +1370,7 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return t_is_prefix ? t-te : ((se-s) - (te-t));
+ return (int) (t_is_prefix ? t-te : ((se-s) - (te-t)));
}
static int my_strnncollsp_ucs2_bin(CHARSET_INFO *cs,
@@ -1387,8 +1387,8 @@ static int my_strnncollsp_ucs2_bin(CHARSET_INFO *cs,
static
int my_strcasecmp_ucs2_bin(CHARSET_INFO *cs, const char *s, const char *t)
{
- uint s_len=strlen(s);
- uint t_len=strlen(t);
+ uint s_len= (uint) strlen(s);
+ uint t_len= (uint) strlen(t);
uint len = (s_len > t_len) ? s_len : t_len;
return my_strncasecmp_ucs2(cs, s, t, len);
}
@@ -1525,7 +1525,7 @@ ulong my_scan_ucs2(CHARSET_INFO *cs __attribute__((unused)),
if (str[0] != '\0' || str[1] != ' ')
break;
}
- return str - str0;
+ return (ulong) (str - str0);
default:
return 0;
}
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index 6b704980d0d..3f934ebd9ce 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -8270,7 +8270,7 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)),
if (b >= (uchar *) end) /* need more bytes */
{
*error= 1;
- return chbeg - beg; /* unexpected EOL */
+ return (uint) (chbeg - beg); /* unexpected EOL */
}
if (ch == 0x8E) /* [x8E][xA0-xDF] */
@@ -8278,7 +8278,7 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)),
if (*b >= 0xA0 && *b <= 0xDF)
continue;
*error= 1;
- return chbeg - beg; /* invalid sequence */
+ return (uint) (chbeg - beg); /* invalid sequence */
}
if (ch == 0x8F) /* [x8F][xA1-xFE][xA1-xFE] */
@@ -8287,7 +8287,7 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)),
if (b >= (uchar*) end)
{
*error= 1;
- return chbeg - beg; /* unexpected EOL */
+ return (uint) (chbeg - beg); /* unexpected EOL */
}
}
@@ -8295,9 +8295,9 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)),
*b >= 0xA1 && *b <= 0xFE) /* [xA1-xFE][xA1-xFE] */
continue;
*error= 1;
- return chbeg - beg; /* invalid sequence */
+ return (uint) (chbeg - beg); /* invalid sequence */
}
- return b - (uchar *) beg;
+ return (uint) (b - (uchar *) beg);
}
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index 6f6d24d8643..53197972dab 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -1932,7 +1932,7 @@ static uchar to_upper_utf8[] = {
static inline int bincmp(const uchar *s, const uchar *se,
const uchar *t, const uchar *te)
{
- int slen=se-s, tlen=te-t;
+ int slen= (int) (se-s), tlen= (int) (te-t);
int len=min(slen,tlen);
int cmp= memcmp(s,t,len);
return cmp ? cmp : slen-tlen;
@@ -2108,7 +2108,7 @@ static uint my_caseup_utf8(CHARSET_INFO *cs, char *src, uint srclen,
src+= srcres;
dst+= dstres;
}
- return dst - dst0;
+ return (uint) (dst - dst0);
}
static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen,
@@ -2141,7 +2141,7 @@ static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen,
static void my_caseup_str_utf8(CHARSET_INFO * cs, char * s)
{
- uint len= strlen(s);
+ uint len= (uint) strlen(s);
my_caseup_utf8(cs, s, len, s, len);
}
@@ -2165,12 +2165,12 @@ static uint my_casedn_utf8(CHARSET_INFO *cs, char *src, uint srclen,
src+= srcres;
dst+= dstres;
}
- return dst - dst0;
+ return (uint) (dst - dst0);
}
static void my_casedn_str_utf8(CHARSET_INFO *cs, char * s)
{
- uint len= strlen(s);
+ uint len= (uint) strlen(s);
my_casedn_utf8(cs, s, len, s, len);
}
@@ -2210,7 +2210,7 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return t_is_prefix ? t-te : ((se-s) - (te-t));
+ return (int) (t_is_prefix ? t-te : ((se-s) - (te-t)));
}
@@ -2284,8 +2284,8 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
t+=t_res;
}
- slen= se-s;
- tlen= te-t;
+ slen= (uint) (se-s);
+ tlen= (uint) (te-t);
res= 0;
if (slen != tlen)
diff --git a/strings/ctype.c b/strings/ctype.c
index 4454d3c45e1..ba6dbaeb887 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -216,7 +216,7 @@ static int cs_value(MY_XML_PARSER *st,const char *attr, uint len)
{
struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
struct my_cs_file_section_st *s;
- int state= (s=cs_file_sec(st->attr,strlen(st->attr))) ? s->state : 0;
+ int state= (int)((s=cs_file_sec(st->attr, (int) strlen(st->attr))) ? s->state : 0);
#ifndef DBUG_OFF
if(0){
diff --git a/strings/decimal.c b/strings/decimal.c
index 4a487f3c9b0..18f920badd3 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -472,7 +472,7 @@ static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
else
{
i= DIG_PER_DEC1 - 1;
- start= (buf_beg - from->buf) * DIG_PER_DEC1;
+ start= (int) ((buf_beg - from->buf) * DIG_PER_DEC1);
}
if (buf_beg < end)
for (; *buf_beg < powers10[i--]; start++) ;
@@ -484,13 +484,13 @@ static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
/* find non-zero decimal digit from the end */
if (buf_end == end - 1 && from->frac)
{
- stop= ((buf_end - from->buf) * DIG_PER_DEC1 +
- (i= ((from->frac - 1) % DIG_PER_DEC1 + 1)));
+ stop= (int) (((buf_end - from->buf) * DIG_PER_DEC1 +
+ (i= ((from->frac - 1) % DIG_PER_DEC1 + 1))));
i= DIG_PER_DEC1 - i + 1;
}
else
{
- stop= (buf_end - from->buf + 1) * DIG_PER_DEC1;
+ stop= (int) ((buf_end - from->buf + 1) * DIG_PER_DEC1);
i= 1;
}
for (; *buf_end % powers10[i++] == 0; stop--);
@@ -794,13 +794,13 @@ internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed)
s1=s;
while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
s++;
- intg=s-s1;
+ intg= (int) (s-s1);
if (s < end_of_string && *s=='.')
{
endp= s+1;
while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp))
endp++;
- frac= endp - s - 1;
+ frac= (int) (endp - s - 1);
}
else
{
@@ -1490,11 +1490,31 @@ decimal_round(decimal_t *from, decimal_t *to, int scale,
buf1+=intg0+frac0-1;
if (scale == frac0*DIG_PER_DEC1)
{
+ int do_inc= FALSE;
DBUG_ASSERT(frac0+intg0 >= 0);
- x=buf0[1]/DIG_MASK;
- if (x > round_digit ||
- (round_digit == 5 && x == 5 && (mode == HALF_UP ||
- (frac0+intg0 > 0 && *buf0 & 1))))
+ switch (round_digit)
+ {
+ case 0:
+ {
+ dec1 *p0= buf0 + (frac1-frac0);
+ for (; p0 > buf0; p0--)
+ if (*p0)
+ {
+ do_inc= TRUE;
+ break;
+ };
+ break;
+ }
+ case 5:
+ {
+ x= buf0[1]/DIG_MASK;
+ do_inc= (x>5) || ((x == 5) &&
+ (mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1)));
+ break;
+ };
+ default:;
+ };
+ if (do_inc)
{
if (frac0+intg0>0)
(*buf1)++;
@@ -1509,6 +1529,7 @@ decimal_round(decimal_t *from, decimal_t *to, int scale,
}
else
{
+ /* TODO - fix this code as it won't work for CEILING mode */
int pos=frac0*DIG_PER_DEC1-scale-1;
DBUG_ASSERT(frac0+intg0 > 0);
x=*buf1 / powers10[pos];
@@ -1563,7 +1584,13 @@ decimal_round(decimal_t *from, decimal_t *to, int scale,
break;
if (buf1-- == to->buf)
{
- decimal_make_zero(to);
+ /* making 'zero' with the proper scale */
+ dec1 *p0= to->buf + frac0 + 1;
+ to->intg=1;
+ to->frac= max(scale, 0);
+ to->sign= 0;
+ for (buf1= to->buf; buf1<p0; buf1++)
+ *buf1= 0;
return E_DEC_OK;
}
}
@@ -1715,14 +1742,14 @@ static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
while (buf1 < stop1 && *buf1 == 0)
buf1++;
start1=buf1;
- intg1=stop1-buf1;
+ intg1= (int) (stop1-buf1);
}
if (unlikely(*buf2 == 0))
{
while (buf2 < stop2 && *buf2 == 0)
buf2++;
start2=buf2;
- intg2=stop2-buf2;
+ intg2= (int) (stop2-buf2);
}
if (intg2 > intg1)
carry=1;
@@ -1734,8 +1761,8 @@ static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
end1--;
while (unlikely((buf2 <= end2) && (*end2 == 0)))
end2--;
- frac1= (end1 - stop1) + 1;
- frac2= (end2 - stop2) + 1;
+ frac1= (int) (end1 - stop1) + 1;
+ frac2= (int) (end2 - stop2) + 1;
while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
buf1++, buf2++;
if (buf1 <= end1)
@@ -2086,7 +2113,7 @@ static int do_div_mod(decimal_t *from1, decimal_t *from2,
/* removing end zeroes */
while (*stop2 == 0 && stop2 >= start2)
stop2--;
- len2= stop2++ - start2;
+ len2= (int) (stop2++ - start2);
/*
calculating norm2 (normalized *start2) - we need *start2 to be large
@@ -2173,7 +2200,7 @@ static int do_div_mod(decimal_t *from1, decimal_t *from2,
if (dcarry)
*--start1=dcarry;
buf0=to->buf;
- intg0=ROUND_UP(prec1-frac1)-(start1-tmp1);
+ intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
frac0=ROUND_UP(to->frac);
error=E_DEC_OK;
if (unlikely(frac0==0 && intg0==0))
diff --git a/strings/xml.c b/strings/xml.c
index d19c3dab241..17f1b400957 100644
--- a/strings/xml.c
+++ b/strings/xml.c
@@ -148,7 +148,7 @@ static int my_xml_enter(MY_XML_PARSER *st, const char *str, uint len)
memcpy(st->attrend,str,len);
st->attrend+=len;
st->attrend[0]='\0';
- return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
+ return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
}
@@ -170,7 +170,7 @@ static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
/* Find previous '.' or beginning */
for( e=p->attrend; (e>p->attr) && (e[0]!='.') ; e--);
- glen = (e[0]=='.') ? (p->attrend-e-1) : p->attrend-e;
+ glen = (uint) ((e[0]=='.') ? (p->attrend-e-1) : p->attrend-e);
if (str && (slen != glen))
{
@@ -180,7 +180,7 @@ static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
return MY_XML_ERROR;
}
- rc = p->leave_xml ? p->leave_xml(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
+ rc = p->leave_xml ? p->leave_xml(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
*e='\0';
p->attrend=e;
@@ -221,7 +221,7 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
sprintf(p->errstr,"1: %s unexpected (ident wanted)",lex2str(lex));
return MY_XML_ERROR;
}
- if(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg))
+ if(MY_XML_OK!=my_xml_leave(p,a.beg,(uint) (a.end-a.beg)))
return MY_XML_ERROR;
lex=my_xml_scan(p,&a);
goto gt;
@@ -240,7 +240,7 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
if (MY_XML_IDENT==lex)
{
- if(MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg))
+ if(MY_XML_OK!=my_xml_enter(p,a.beg,(uint) (a.end-a.beg)))
return MY_XML_ERROR;
}
else
@@ -258,9 +258,9 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
lex=my_xml_scan(p,&b);
if ( (lex==MY_XML_IDENT) || (lex==MY_XML_STRING) )
{
- if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
- (MY_XML_OK!=my_xml_value(p,b.beg,b.end-b.beg)) ||
- (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ if((MY_XML_OK!=my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) ||
+ (MY_XML_OK!=my_xml_value(p,b.beg,(uint) (b.end-b.beg))) ||
+ (MY_XML_OK!=my_xml_leave(p,a.beg,(uint) (a.end-a.beg))))
return MY_XML_ERROR;
}
else
@@ -272,8 +272,8 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
}
else if ( (MY_XML_STRING==lex) || (MY_XML_IDENT==lex) )
{
- if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
- (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ if((MY_XML_OK!=my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) ||
+ (MY_XML_OK!=my_xml_leave(p,a.beg,(uint) (a.end-a.beg))))
return MY_XML_ERROR;
}
else
@@ -321,7 +321,7 @@ gt:
my_xml_norm_text(&a);
if (a.beg!=a.end)
{
- my_xml_value(p,a.beg,a.end-a.beg);
+ my_xml_value(p,a.beg,(uint) (a.end-a.beg));
}
}
}
@@ -384,7 +384,7 @@ uint my_xml_error_pos(MY_XML_PARSER *p)
if (s[0]=='\n')
beg=s;
}
- return p->cur-beg;
+ return (uint) (p->cur-beg);
}
uint my_xml_error_lineno(MY_XML_PARSER *p)
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 088fbf53698..b1ff78bdaf6 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -1,5 +1,9 @@
%define mysql_version @VERSION@
-%ifarch i386
+# use "rpmbuild --with static" or "rpm --define '_with_static 1'" (for RPM 3.x)
+# to enable static linking (off by default)
+%{?_with_static:%define STATIC_BUILD 1}
+%{!?_with_static:%define STATIC_BUILD 0}
+%if %{STATIC_BUILD}
%define release 0
%else
%define release 0.glibc23
@@ -342,7 +346,7 @@ make clean
# so don't link statically there
#
BuildMySQL "--disable-shared \
-%ifarch i386
+%if %{STATIC_BUILD}
--with-mysqld-ldflags='-all-static' \
--with-client-ldflags='-all-static' \
$USE_OTHER_LIBC_DIR \
@@ -663,6 +667,13 @@ fi
# itself - note that they must be ordered by date (important when
# merging BK trees)
%changelog
+* Tue Jun 14 2005 Lenz Grimmer <lenz@mysql.com>
+
+- Do not build statically on i386 by default, only when adding either "--with
+ static" or "--define '_with_static 1'" to the RPM build options. Static
+ linking really only makes sense when linking against the specially patched
+ glibc 2.2.5.
+
* Mon Jun 06 2005 Lenz Grimmer <lenz@mysql.com>
- added mysql_client_test to the "bench" subpackage (BUG 10676)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a4bcd38afb1..ee3e31aa040 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -17,6 +17,11 @@
## Process this file with automake to create Makefile.in
+if HAVE_YASSL
+ yassl_dummy_link_fix= $(top_srcdir)/extra/yassl/src/dummy.cpp
+else
+ yassl_dummy_link_fix=
+endif
EXTRA_DIST = auto_increment.res auto_increment.tst \
function.res function.tst lock_test.pl lock_test.res \
export.pl big_record.pl \
@@ -38,7 +43,9 @@ LDADD = @CLIENT_EXTRA_LDFLAGS@ \
$(top_builddir)/libmysql/libmysqlclient.la
mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) \
$(top_builddir)/mysys/libmysys.a
-mysql_client_test_SOURCES= mysql_client_test.c
+mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix)
+insert_test_SOURCES= insert_test.c $(yassl_dummy_link_fix)
+select_test_SOURCES= select_test.c $(yassl_dummy_link_fix)
insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
select_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index b6ca4996c70..585763c164d 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -12995,6 +12995,19 @@ static void test_bug9478()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
+ {
+ char buff[8];
+ /* Fill in the fethc packet */
+ int4store(buff, stmt->stmt_id);
+ buff[4]= 1; /* prefetch rows */
+ rc= ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH, buff,
+ sizeof(buff), 0,0,1) ||
+ (*mysql->methods->read_query_result)(mysql));
+ DIE_UNLESS(rc);
+ if (!opt_silent && i == 0)
+ printf("Got error (as expected): %s\n", mysql_error(mysql));
+ }
+
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -13039,8 +13052,8 @@ static void test_bug9478()
/* Fill in the execute packet */
int4store(buff, stmt->stmt_id);
buff[4]= 0; /* Flag */
- int4store(buff+5, 1); /* Return 1 row */
- rc= ((*mysql->methods->advanced_command)(mysql, COM_EXECUTE, buff,
+ int4store(buff+5, 1); /* Reserved for array bind */
+ rc= ((*mysql->methods->advanced_command)(mysql, COM_STMT_EXECUTE, buff,
sizeof(buff), 0,0,1) ||
(*mysql->methods->read_query_result)(mysql));
DIE_UNLESS(rc);
@@ -13146,6 +13159,66 @@ static void test_bug9643()
}
/*
+ Bug#11111: fetch from view returns wrong data
+*/
+
+static void test_bug11111()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[2];
+ char buf[2][20];
+ ulong len[2];
+ int i;
+ int rc;
+ const char *query= "SELECT DISTINCT f1,ff2 FROM v1";
+
+ myheader("test_bug11111");
+
+ rc= mysql_query(mysql, "drop table if exists t1, t2, v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "drop view if exists t1, t2, v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "create table t1 (f1 int, f2 int)");
+ myquery(rc);
+ rc= mysql_query(mysql, "create table t2 (ff1 int, ff2 int)");
+ myquery(rc);
+ rc= mysql_query(mysql, "create view v1 as select * from t1, t2 where f1=ff1");
+ myquery(rc);
+ rc= mysql_query(mysql, "insert into t1 values (1,1), (2,2), (3,3)");
+ myquery(rc);
+ rc= mysql_query(mysql, "insert into t2 values (1,1), (2,2), (3,3)");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+
+ mysql_stmt_prepare(stmt, query, strlen(query));
+ mysql_stmt_execute(stmt);
+
+ bzero(bind, sizeof(bind));
+ for (i=0; i < 2; i++)
+ {
+ bind[i].buffer_type= MYSQL_TYPE_STRING;
+ bind[i].buffer= (gptr *)&buf[i];
+ bind[i].buffer_length= 20;
+ bind[i].length= &len[i];
+ }
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent)
+ printf("return: %s", buf[1]);
+ DIE_UNLESS(!strcmp(buf[1],"1"));
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop view v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "drop table t1, t2");
+ myquery(rc);
+}
+
+/*
Check that proper cleanups are done for prepared statement when
fetching thorugh a cursor.
*/
@@ -13206,6 +13279,117 @@ static void test_bug10729()
myquery(rc);
}
+
+/*
+ Check that mysql_next_result works properly in case when one of
+ the statements used in a multi-statement query is erroneous
+*/
+
+static void test_bug9992()
+{
+ MYSQL *mysql1;
+ MYSQL_RES* res ;
+ int rc;
+
+ myheader("test_bug9992");
+
+ if (!opt_silent)
+ printf("Establishing a connection with option CLIENT_MULTI_STATEMENTS..\n");
+
+ mysql1= mysql_init(NULL);
+
+ if (!mysql_real_connect(mysql1, opt_host, opt_user, opt_password,
+ opt_db ? opt_db : "test", opt_port, opt_unix_socket,
+ CLIENT_MULTI_STATEMENTS))
+ {
+ fprintf(stderr, "Failed to connect to the database\n");
+ DIE_UNLESS(0);
+ }
+
+
+ /* Sic: SHOW DATABASE is incorrect syntax. */
+ rc= mysql_query(mysql1, "SHOW TABLES; SHOW DATABASE; SELECT 1;");
+
+ if (rc)
+ {
+ fprintf(stderr, "[%d] %s\n", mysql_errno(mysql1), mysql_error(mysql1));
+ DIE_UNLESS(0);
+ }
+
+ if (!opt_silent)
+ printf("Testing mysql_store_result/mysql_next_result..\n");
+
+ res= mysql_store_result(mysql1);
+ DIE_UNLESS(res);
+ mysql_free_result(res);
+ rc= mysql_next_result(mysql1);
+ DIE_UNLESS(rc == 1); /* Got errors, as expected */
+
+ if (!opt_silent)
+ fprintf(stdout, "Got error, sa expected:\n [%d] %s\n",
+ mysql_errno(mysql1), mysql_error(mysql1));
+
+ mysql_close(mysql1);
+}
+
+
+/* Bug#10736: cursors and subqueries, memroot management */
+
+static void test_bug10736()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char a[21];
+ int rc;
+ const char *stmt_text;
+ int i= 0;
+ ulong type;
+
+ myheader("test_bug10736");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key,"
+ "name VARCHAR(20) NOT NULL)");
+ rc= mysql_query(mysql, "insert into t1 (id, name) values "
+ "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_execute(stmt, rc);
+ stmt_text= "select name from t1 where name=(select name from t1 where id=2)";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ bzero(bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void*) a;
+ bind[0].buffer_length= sizeof(a);
+ mysql_stmt_bind_result(stmt, bind);
+
+ for (i= 0; i < 3; i++)
+ {
+ int row_no= 0;
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
+ {
+ if (!opt_silent)
+ printf("%d: %s\n", row_no, a);
+ ++row_no;
+ }
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+ }
+ rc= mysql_stmt_close(stmt);
+ DIE_UNLESS(rc == 0);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -13439,6 +13623,9 @@ static struct my_tests_st my_tests[]= {
{ "test_bug9478", test_bug9478 },
{ "test_bug9643", test_bug9643 },
{ "test_bug10729", test_bug10729 },
+ { "test_bug11111", test_bug11111 },
+ { "test_bug9992", test_bug9992 },
+ { "test_bug10736", test_bug10736 },
{ 0, 0 }
};
@@ -13543,23 +13730,6 @@ static void print_test_output()
}
}
-
-static void check_mupltiquery_bug9992()
-{
-
- MYSQL_RES* res ;
- mysql_query(mysql,"SHOW TABLES;SHOW DATABASE;SELECT 1;");
-
- fprintf(stdout, "\n\n!!! check_mupltiquery_bug9992 !!!\n");
- do
- {
- if (!(res= mysql_store_result(mysql)))
- return;
- mysql_free_result(res);
- } while (!mysql_next_result(mysql));
- fprintf(stdout, "\n\n!!! SUCCESS !!!\n");
- return;
-}
/***************************************************************************
main routine
***************************************************************************/
@@ -13625,10 +13795,7 @@ int main(int argc, char **argv)
}
client_disconnect(); /* disconnect from server */
-
- client_connect(CLIENT_MULTI_STATEMENTS);
- check_mupltiquery_bug9992();
- client_disconnect();
+
free_defaults(defaults_argv);
print_test_output();
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 036f0b8a76e..651ef2d22b3 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -15,13 +15,18 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Process this file with automake to create Makefile.in
+if HAVE_YASSL
+ yassl_dummy_link_fix= $(top_srcdir)/extra/yassl/src/dummy.cpp
+else
+ yassl_dummy_link_fix=
+endif
INCLUDES=-I$(top_srcdir)/include $(openssl_includes) \
-I$(top_builddir)/include
LDADD= @CLIENT_EXTRA_LDFLAGS@ \
$(top_builddir)/libmysql_r/libmysqlclient_r.la \
@openssl_libs@ @ZLIB_LIBS@
bin_PROGRAMS= mysqltestmanager
-mysqltestmanager_SOURCES= mysqlmanager.c
+mysqltestmanager_SOURCES= mysqlmanager.c $(yassl_dummy_link_fix)
mysqltestmanager_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
DEF= -DUNDEF_THREADS_HACK
diff --git a/vio/Makefile.am b/vio/Makefile.am
index 22e706efe4c..cd4212089c4 100644
--- a/vio/Makefile.am
+++ b/vio/Makefile.am
@@ -14,22 +14,25 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+if HAVE_YASSL
+ yassl_dummy_link_fix= $(top_srcdir)/extra/yassl/src/dummy.cpp
+else
+ yassl_dummy_link_fix=
+endif
INCLUDES= -I$(top_srcdir)/include $(openssl_includes)
LDADD= @CLIENT_EXTRA_LDFLAGS@ $(openssl_libs)
pkglib_LIBRARIES= libvio.a
noinst_PROGRAMS = test-ssl test-sslserver test-sslclient
noinst_HEADERS= vio_priv.h
-test_ssl_SOURCES= test-ssl.c $(top_srcdir)/extra/yassl/src/dummy.cpp
+test_ssl_SOURCES= test-ssl.c $(yassl_dummy_link_fix)
test_ssl_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs)
-test_sslserver_SOURCES= test-sslserver.c \
- $(top_srcdir)/extra/yassl/src/dummy.cpp
+test_sslserver_SOURCES= test-sslserver.c $(yassl_dummy_link_fix)
test_sslserver_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs)
-test_sslclient_SOURCES= test-sslclient.c \
- $(top_srcdir)/extra/yassl/src/dummy.cpp
+test_sslclient_SOURCES= test-sslclient.c $(yassl_dummy_link_fix)
test_sslclient_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs)
diff --git a/vio/viosocket.c b/vio/viosocket.c
index ee8e85880ba..c9df242b5c4 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -425,6 +425,7 @@ int vio_close_pipe(Vio * vio)
void vio_ignore_timeout(Vio *vio __attribute__((unused)),
+ uint which __attribute__((unused)),
uint timeout __attribute__((unused)))
{
}